gRPC vs REST
Two different mental models
Section titled “Two different mental models”REST and gRPC solve the same broad problem — one program talking to another — but they frame it differently.
- REST thinks in resources. You have nouns (
/users/42), and you act on them with a small fixed set of verbs (GET,POST,PUT,DELETE). The data is usually JSON, and the contract is often a document (OpenAPI) or just convention. - gRPC thinks in procedures. You have methods (
GetUser,CreateOrder,StreamPrices), each with a typed request and response defined in a.proto. The data is binary protobuf, and the contract is the schema itself.
Neither model is “correct” — they optimize for different things.
The honest comparison
Section titled “The honest comparison”| REST + JSON | gRPC + Protobuf | |
|---|---|---|
| Payload | Text (JSON) — human-readable, larger | Binary — compact, fast to parse |
| Contract | Optional (OpenAPI / convention) | Mandatory (.proto), enforced by codegen |
| Browser support | Native, universal | Needs gRPC-Web + a proxy |
| Streaming | Awkward (SSE, long-poll) | First-class, bidirectional |
| Human debuggability | curl and read it | Needs tooling (grpcurl, reflection) |
| Codegen / type safety | Add-on, varies | Built in, across 11+ languages |
| Best fit | Public APIs, browsers, simple CRUD | Internal service-to-service, low latency, streaming |
Why gRPC is faster (and when it matters)
Section titled “Why gRPC is faster (and when it matters)”Two things make gRPC efficient on the wire:
flowchart TB
subgraph rest["REST + JSON"]
r1["parse text JSON
(reflective, larger)"] --> r2["new connection
or HTTP/1.1 head-of-line"]
end
subgraph grpc["gRPC + Protobuf"]
g1["decode binary protobuf
(schema-driven, compact)"] --> g2["HTTP/2 multiplexing
many calls, one connection"]
end - Protobuf is smaller and cheaper to decode than JSON. Fields are tagged by number, not by name, and values are packed as binary. There is no reflective key-matching and no text parsing.
- HTTP/2 multiplexing lets many in-flight calls share one connection without blocking each other (the next lesson goes deep on this).
But be honest about scale: for a request every few seconds, this difference is invisible. It matters when you make thousands of calls per second between services, or move large/streaming payloads.
When NOT to use gRPC
Section titled “When NOT to use gRPC”gRPC is a great default for internal microservices, but it is the wrong tool when:
- The client is a browser and you can’t run a proxy. Browsers can’t speak raw gRPC; you need gRPC-Web plus a translating proxy (Envoy or the built-in one). For a simple public web API, REST is less friction.
- You want a public, third-party-friendly API. Most external developers expect
curl, JSON, and an OpenAPI page. gRPC raises the barrier to entry. - The API is trivial CRUD with low traffic. The
.prototoolchain and binary debugging are overhead you won’t recoup. - Human-readable traffic is a hard requirement (some compliance or debugging setups). Binary frames need extra tooling to inspect.