gRPC in Depth: Calling Another Service Without Pretending the Network Is Reliable
Algomi Research · Created 2026-09-26 · Updated 2026-10-15 · System Design
Page 1 of 1
A phone on every desk
Picture a school office where every desk has a phone and there is one shared directory. To reach the librarian, you dial her extension and ask a question. You do not need to know which room she is in. You only need the directory to say what she can answer and what to say.
That is the idea behind gRPC. It lets one program call a function that runs in another program, often on another computer, as if it were a local function. The "directory" is a written contract. Tools read the contract and generate the code that dials, packs the question, and unpacks the answer.
The picture has one trap. A desk phone can ring unanswered, the line can drop mid-sentence, and the librarian can say "yes" just as the call cuts out. A generated function looks like a local call, but the network under it is not local. This guide explains how gRPC works, and how to design calls that stay safe when the line misbehaves.
It builds on the REST, GraphQL, and gRPC section of our networking and APIs guide, and it borrows ideas from our payment system and reliability guides. Our running example is a school library platform with a reservation service that calls a catalog service and an inventory service. It is an original teaching design. Behaviour we describe as gRPC's own is taken from the official gRPC documentation, and advice that is ours is labelled as our design.
1. The contract comes first
In gRPC you write the contract before the code. It is a .proto file, written in Protocol Buffers, that names the services, their calls, and the messages they exchange.
syntax = "proto3";
service Reservations {
// One request, one response.
rpc HoldCopy(HoldCopyRequest) returns (HoldCopyResponse);
// One request, a stream of updates back.
rpc WatchQueue(WatchQueueRequest) returns (stream QueueUpdate);
}
message HoldCopyRequest {
string book_id = 1;
string student_id = 2;
string request_id = 3; // our idempotency key
}
The tools generate a client stub and a server skeleton in each language you use. A Java service and a Python client then share one source of truth. This is the main benefit of gRPC: the shape of every call is written down, checked by machines, and the same for everyone.
The numbers after the equals signs are field numbers. They matter more than the names. The Protocol Buffers encoding guide explains that the binary form uses only the field number as the key, so the name and type can only be worked out by reading the definition. That single fact drives the rules for changing a contract safely.
Change
Safe?
Why
Add a new field with a new number
Yes
Old readers skip fields they do not know
Delete a field and reserve its number and name
Yes
The number can never be reused by mistake
Reuse a deleted field's number
No
Old data and old code will misread it
Change a field's type
No
Deserialization fails or silently misreads
Add a required field
No
Old clients cannot send it
Change a default value
No
Old and new sides see different answers
These rules come from the Protocol Buffers dos and don'ts. It also advises giving every enum an unspecified first value, and using the well-known types for times and durations instead of inventing your own. When you remove a field, write reserved 2, 3; so the numbers stay retired. Because a client and server are deployed at different times, both old and new versions are always alive together, so a change that is safe in only one direction is not safe.
With a contract in hand, the first working system is just services calling each other through generated stubs:
Step 1: the smallest design that works.
You've reached the free preview of this post.
Subscribe to the Blogs plan (₹99/mo) — or use any Algomi Suite, Career, Investor, or Trader plan — to keep reading.