gRPC API Design
Designing service interfaces in a schema-first binary protocol — where the discipline differs from REST and where the mistakes are permanent.
Definition
A gRPC API is defined in a schema before any code exists. Services, methods, request and response messages are declared, and clients and servers are generated from that declaration in every language the estate uses.
What changes relative to REST
The contract is executable, not descriptive. In REST the specification describes the API and the code implements it, and the two drift. Here the schema generates both sides, so drift is structurally impossible.
Method naming replaces resource modelling. REST pushes you toward nouns and a small verb set;
gRPC lets you name the operation. That is more expressive and considerably easier to get wrong — an
API of arbitrary verbs becomes an unnavigable surface within a year. The discipline that replaces
REST's constraint is naming convention: a standard set of verbs (Get, List, Create, Update,
Delete, BatchGet) applied consistently, with custom methods as deliberate exceptions.
Field numbers are forever. A field's wire identity is its number, not its name. Renaming a field is free; reusing a number is a data corruption bug that surfaces at runtime in already-deployed clients. Numbers of removed fields must be reserved permanently.
Design rules worth adopting
- Wrap everything in a message, even when one field would do. A method taking a bare string can never gain a second parameter compatibly; a method taking a message always can. This single rule prevents most future breaking changes.
- Never reuse or renumber fields. Reserve removed numbers explicitly.
- Additive change only. New fields are optional and unknown fields are ignored by older clients, which is what makes rolling deployment safe.
- Propagate deadlines. A deadline set by the caller travels with the request, so downstream work is abandoned when nobody is waiting. This is the largest resilience benefit the protocol offers and it is frequently unused.
- Pagination on every list method, from the first version. Retrofitting it is a breaking change.
- Standard error model with typed details, not string messages parsed by clients.
Industry example
Google's published API design guidance encodes years of experience with exactly these failures, and its most transferable idea is resource-oriented design applied to RPC: even in a protocol that allows arbitrary methods, modelling the API as resources with standard methods produces surfaces that engineers can predict without reading documentation.
The reason this matters more at scale than at small scale is discoverability. With ten methods, consistency is a nicety. With ten thousand across hundreds of services, an engineer must be able to guess what a method is called and what it returns, and a consistent convention is the only mechanism that delivers that.
Failure scenarios
- A field number reused, so old clients deserialise a new field as an old one — silent, typed corruption.
- A required-by-convention field added, breaking clients that do not send it.
- Deadlines not propagated, so a cancelled request continues consuming resources through six downstream hops.
- An arbitrary verb surface that nobody can navigate.
- Streaming used where request/response would do, adding complexity and connection state for no gain.
Interview question
"You need to remove a field from a widely-used protobuf message. Walk me through the safe sequence."