gRPC & Protobuf — Contracts, Streaming & API Evolution
gRPC is HTTP/2 + Protocol Buffers + generated stubs: a contract-first RPC stack for service-to-service calls. Interviewers care less about binary speed and more about contracts, streaming shapes, evolution rules, and when gRPC is the wrong tool (browsers without grpc-web, public REST ecosystems). This hub maps the cluster: schemas, unary vs streaming, deadlines/errors, load balancing/channels, and the REST/GraphQL decision matrix.
- 1Gist
- 2Maps
- 3Q&A
- 4Sandbox
Voice readout needs Web Speech Synthesis in this browser.
How you share the contract
Prefer
Shared Protobuf .proto + codegen
Typed stubs, wire-compatible evolution, small payloads. Field numbers are the identity; buf breaking checks catch reuse. Fits internal meshes and polyglot services.
- protoc / buf generate language stubs so clients and servers cannot silently drift.
- Streaming, deadlines, and status codes ride the same runtime.
- Tooling required; harder to curl by hand — that is the trade, not a bug.
Alternative
Undocumented JSON over HTTP
Fast to prototype. Silent breakage, no schema enforcement, no evolution discipline. OpenAPI + generated clients is the public-HTTP middle path — great for browsers, awkward for streaming.
- OpenAPI wins for public HTTP APIs; hand-edited specs still drift.
- Public REST naming and versioning live in the API Design cluster — pointer only.
- Interviewers ding “we just POST JSON” with no field identity story.
What a unary call actually does
IDL → codegen → HTTP/2 stream → handler → typed result. Depth on schemas, streaming, deadlines, and channels lives in siblings.
- 1
IDL
.proto defines messages and service RPCs. Field numbers are forever. - 2
Codegen
protoc / buf generates language stubs. App code calls typed methods. - 3
Transport
HTTP/2 multiplexed streams, binary framing. One channel, many RPCs. - 4
Runtime
Channel, stub, interceptors, deadlines, status + trailers. - 5
Evolve or refuse
Add optional fields; never reuse numbers. Or pick REST/GraphQL when gRPC is the wrong tool.
Overview
Interviewers care less about binary speed and more about contracts, streaming shapes, evolution rules, and when gRPC is the wrong tool.
Prefer gRPC when: internal mesh, polyglot services, streaming, strict backward compatibility, bandwidth-sensitive links.
Prefer REST/JSON when: public browser APIs, partner ecosystems, caching proxies, human curl workflows. Path/versioning depth: API Design. POST retry keys: idempotency — do not re-teach here.
You should be able to:
- Draw the stub → channel → handler path without a Client subgraph.
- Classify an RPC as unary / server-stream / client-stream / bidi.
- Point at the five sibling pages instead of dumping every rule on one slide.
What gRPC actually is
- IDL —
.protodefines messages and service RPCs. - Codegen —
protoc/ buf generates language stubs. - Transport — HTTP/2 multiplexed streams, binary framing.
- Runtime — channel, stub, interceptors, deadlines, status + trailers.
Flow
- 1
1 App calls stub
- next2 Stub serializes Protobuf
- 2
2 Stub serializes Protobuf
- next3 Channel picks HTTP/2
- 3
3 Channel picks HTTP/2
- next4 Server demux stream
- 4
4 Server demux stream
- next5 Handler deserializes
- 5
5 Handler deserializes
- next6 Business logic
- 6
6 Business logic
- next7 Response or stream
- 7
7 Response or stream
- next8 Stub returns typed result
- 8
8 Stub returns typed result
Lesson map
gRPC & Protobuf — Contracts, Streaming & API Evolution
gRPC is HTTP/2 + Protocol Buffers + generated stubs: a contract-first RPC stack for service-to-service calls. Interviewers care less about binary speed and more about contracts, streaming shapes, evolution rules, and when gRPC is the wrong tool (browsers without grpc-web, public REST ecosystems). This hub maps the cluster: schemas, unary vs streaming, deadlines/errors, load balancing/channels, and the REST/GraphQL decision matrix.
Architecture. Architecture
Select a node to see why it exists, or an edge to see the protocol, direction, effect, and consequence.
Mermaid export
flowchart TB a["1 App calls stub"] b["2 Stub serializes Protobuf"] c["3 Channel picks HTTP/2"] d["4 Server demux stream"] a -->|1 App calls stub to 2 Stub serializes Protobuf| b b -->|2 Stub serializes Protobuf| c c -->|3 Channel picks HTTP/2| d
Single-column path. No client subgraph — the stub and channel are steps, not a boxed swimlane.
Streaming shapes preview
| RPC type | Client to Server | Server to Client | Fits |
|---|---|---|---|
| Unary | 1 | 1 | CRUD-like calls |
| Server-stream | 1 | N | Large downloads, live feeds |
| Client-stream | N | 1 | Upload / aggregate |
| Bidirectional | N | N | Chat, sensors, sync |
Details: Unary vs Streaming RPCs. A repeated field is still one message; streaming is messages over time with flow control.
Evolution rules preview
- Field numbers are the wire identity — never reuse.
- Add optional fields; do not renumber or change types in place.
- Use
reservedfor deleted numbers/names. - Deep dive: Protobuf Schemas.
When NOT to use gRPC
- Browser-first public APIs without grpc-web / Envoy translate.
- Partners who only speak REST and OpenAPI.
- Heavy CDN caching of GET-like reads.
- Ops culture that lives in curl + JSON.
The honest decision matrix is gRPC vs REST/JSON & GraphQL.
Comparative: gRPC vs just HTTP/JSON
| Concern | gRPC | REST/JSON |
|---|---|---|
| Contract | .proto + stubs | OpenAPI / informal |
| Streaming | First-class on HTTP/2 | SSE / chunked / WebSocket |
| Browser | Needs grpc-web | Native fetch |
| Payload size | Compact binary | Larger text |
| Debuggability | grpcurl / reflection | curl + browser |
Sandbox: unary mental model (Python)
Stand-in channel + stub. Timeouts become DEADLINE_EXCEEDED — the real deadline tree is the deadlines lesson.
Press Run. Snippets must be self-contained — no network, files, or native modules.
Same mental model (TypeScript)
Press Run. Snippets must be self-contained — no network, files, or native modules.
Deep dive · Where neighboring clusters fit — pointer only
Public REST naming, nesting, and versioning: API Design. Safe POST retries: idempotency keys and idempotent HTTP methods. End-to-end budgets that gRPC deadlines implement: timeouts & deadline propagation. L4 vs L7 and Maglev/P2C live in Load Balancing — this cluster only covers gRPC channels. Do not re-teach those lessons here.
Pitfalls
Sketch GetUser as unary. Where does the stub serialize? Where does the channel pick an HTTP/2 stream? What field number is user_id? When would you switch this to REST/JSON for partners?
Interview Q&A
What is gRPC in one sentence?
Answer
HTTP/2-based RPC with Protobuf contracts and generated stubs, plus a standard status/deadline/streaming model.
Why not always use gRPC for every API?
Answer
Browsers, public partner ecosystems, CDN caching, and human curl workflows often favor REST/JSON. gRPC shines inside the mesh. Decision depth: gRPC vs REST/JSON & GraphQL. REST surface design: API Design.
What breaks when two teams edit the same .proto casually?
Answer
Reused field numbers, renamed enums without reserved, and incompatible type changes — silent wire corruption or decode failures. Protobuf schemas.
How does streaming differ from returning a list?
Answer
Streaming delivers messages over time with flow control; a list is one message. Memory and latency profiles differ. Unary vs streaming.
Where do deadlines live?
Answer
On the call context, propagated across hops — see Deadlines, Cancellation & Error Model. Remaining-budget theory: timeouts & budgets — do not recap breakers here.
Client-side LB vs proxy LB?
Answer
Both exist; gRPC often does client-side LB with name resolution — see Load Balancing, Name Resolution & Channel Health. Maglev/P2C depth stays in the Load Balancing cluster.
How do you evolve a field from required-ish to optional?
Answer
In proto3 everything is optional-by-default; never reuse numbers; add new fields; reserve deleted ones.
When would you pick GraphQL instead?
Answer
Flexible BFF queries for many UI shapes — see gRPC vs REST/JSON & GraphQL. GraphQL is usually a facade over gRPC/REST leaves, not a replacement for the mesh.