About

sprout · Jun 18, 2026 · 6 min read

gRPC & Contracts

gRPC (short for Google Remote Procedure Call) is an open-source framework that lets one program call a function that runs inside a different program, over a network, almost as easily as calling a function inside its own code.[1] Instead of designing URL endpoints and request bodies like you do with REST, you define a contract in a .proto file — a language-neutral description of which functions exist and what data they take. gRPC then generates matching client and server code in many languages (Go, Python, Java, C#, Node.js), so the calling code looks like a regular function call, with the network layer hidden underneath.

The one problem everything here exists to solve

Most companies do not run one program. They run many separate programs — usually called services — each with its own stored information, each able to be restarted or updated without touching the others. Sometimes one service needs to ask another to do something. Because they are genuinely separate programs, one cannot reach into the other's code or memory. The only way is to send an actual message across a network connection, and wait for a message back.

That introduces a problem that never exists inside a single program: both sides must agree, in advance and in writing, on exactly what a message contains. If one side changes what a message looks like without telling the other, both programs can keep running perfectly fine on their own while quietly misunderstanding each other for a long time before anyone notices.

That written agreement — "here is exactly what this piece of information contains, so both sides read it the same way" — is called a contract.[2] gRPC and a shared Contracts code folder are two different tools for writing and enforcing that same kind of agreement, for two different situations:

Both situations need the same underlying agreement about message contents; they just write it in a different format, because the two tools work differently underneath.

The .proto file is the contract (ask, and wait)

gRPC solves the agreement problem by making both sides read the exact same .proto file — a plain text file, nothing more complicated than that. A small code generator reads that one file and writes ready-to-use code for both sides at once: the side asking and the side answering. Because both sides are generated from the one identical starting file, they cannot end up disagreeing about what a message contains. A change that breaks the agreement fails immediately at build time — not later, quietly, while real data is already flowing through a running system.

A complete, working example — a coffee shop with two services, a storefront and a kitchen:

syntax = "proto3";
package coffee_shop;

service KitchenGrpc {
    rpc PlaceOrder (PlaceOrderRequest) returns (OrderReceipt);
    rpc GetOrderStatus (GetOrderStatusRequest) returns (OrderStatus);
}

message PlaceOrderRequest {
    string customer_id = 1;
    repeated LineItem items = 2;
}

message LineItem {
    string name = 1;
    int32 quantity = 2;
    int64 price_minor = 3;
}

message OrderReceipt {
    string order_id = 1;
    int64 total_minor = 2;
}

Line by line, in plain terms:

Once this file exists, the kitchen program generates code that waits for these requests and runs real logic when one arrives. The storefront program generates different code from that exact same file — code that lets a developer write what looks like an ordinary function call while secretly doing a real network round-trip underneath. Same file, two generated results, one on each side — and that is the entire mechanism.

The same idea without gRPC (announce, and move on)

For the "announce and move on" situation, the contract is written as a small shared piece of code instead of a .proto file — inside a folder every service builds against, usually named something like Contracts:

public record OrderPlacedIntegrationEvent(Guid OrderId, Guid CustomerId) : IntegrationEvent;

Why does this one small file need to live in a folder shared by every program, instead of inside the program that announces it? Because every program that might react needs to read the exact same description of the announcement. If each service separately wrote its own copy of "what does an order-placed announcement look like", the copies could quietly drift apart — one side expecting a field spelled one way, another expecting something slightly different — and nothing would catch that until a real announcement arrived and was misread. One true definition, in one shared place that every program builds against, makes that kind of drift structurally impossible.

The four communication patterns

gRPC supports four types of call, unlike REST which has one (request/response):

Pattern What happens Typical use
Unary One request, one response — the same shape as a REST call Most standard operations
Server streaming Client sends one request; server streams back many responses Live data feeds, log tailing, large result sets
Client streaming Client streams many messages; server replies once Uploading files in chunks, batches of sensor data
Bidirectional streaming Both sides stream independently over one persistent connection Real-time chat, collaborative tools, telemetry

gRPC vs REST

Feature gRPC REST
Protocol HTTP/2 HTTP/1.1 or HTTP/2
Serialization Protocol Buffers (binary) JSON (text)
Contract Required (.proto file) Optional (OpenAPI)
Code generation Built-in Optional tooling
Streaming 4 patterns Limited (SSE, WebSockets)
Browser support Limited (needs gRPC-Web) Full
Human-readable No Yes

When to use gRPC

gRPC is the right choice for internal service-to-service communication in a Microservices Architecture: the strict contract prevents API drift between teams, the binary encoding reduces payload size and latency, and streaming covers real-time cases that REST handles awkwardly. It is widely used at Google, Netflix, and Spotify for exactly this reason.

For public APIs consumed by browsers or third-party developers, REST remains the better default — gRPC's binary format is hard to inspect, and browser support needs the gRPC-Web adapter. Many teams use both: gRPC internally between services, and REST or GraphQL externally for client-facing APIs.


Sources

  1. gRPC Core Concepts — grpc.io
  2. A beginner's guide to gRPC — freeCodeCamp