Overview
REST models an API as resources addressed by URLs and manipulated with HTTP verbs, usually
carrying JSON. gRPC models an API as functions you call: you define services and messages in a
.proto file, a code generator emits typed clients and server stubs in your languages, and calls
travel as binary Protocol Buffers over HTTP/2. One is an architectural style riding on the web's
native infrastructure; the other is a high-performance RPC framework with a compiler.
The contract is the clearest difference. In gRPC it's mandatory and machine-checked:
service UserService {
rpc GetUser (GetUserRequest) returns (User);
rpc WatchUpdates (GetUserRequest) returns (stream UserEvent);
}
message GetUserRequest {
int64 id = 1;
}In REST, the equivalent (an OpenAPI spec) is optional, and drifts from reality unless a team enforces it.
Feature comparison
| gRPC | REST | |
|---|---|---|
| Transport | HTTP/2 (multiplexed, binary framing) | Any HTTP version, most commonly HTTP/1.1 with JSON |
| Payload | Protocol Buffers, binary, compact | JSON (typically), text, human-readable |
| Contract | Required .proto schema, code-generated clients and servers | Convention plus optional OpenAPI |
| Streaming | Unary, server-streaming, client-streaming, and bidirectional built in | Request/response; streaming needs SSE or WebSockets alongside |
| Browser support | Not directly; needs gRPC-Web and a proxy (e.g. Envoy) | Universal; every browser, curl, and HTTP client |
| Caching | No HTTP-level caching semantics | Native GET caching, ETags, CDNs |
| Deadlines / cancellation | First-class, propagate across service hops | Rolled by hand with timeouts per hop |
| Error model | Structured status codes plus typed error details | HTTP status codes, error body shape is per-API convention |
| Debuggability | Binary on the wire; needs grpcurl/tooling | Read it in a terminal or browser dev tools |
| Best fit | Internal service-to-service, polyglot microservices | Public APIs, web clients, anything third parties consume |
Where REST tends to win
Anything exposed to the outside world. Every language, browser, proxy, gateway, and developer on
earth already speaks HTTP+JSON; a public REST API can be explored with curl and cached by a CDN
with zero client tooling. When your consumers are unknown third parties, the universality and
self-evidence of REST beats gRPC's efficiency, and for typical CRUD services the performance
difference rarely matters next to database and network time.
Where gRPC tends to win
Inside the datacenter. For service-to-service traffic at volume, binary protobuf over multiplexed HTTP/2 means smaller payloads, less serialization CPU, and lower tail latency than JSON over HTTP/1.1. Generated clients keep a polyglot fleet honest, a Go service calling a Java service gets compile-time-checked types in both directions, and deadlines that propagate through call chains prevent one slow dependency from hanging a whole request tree. Bidirectional streaming on one connection covers real-time use cases REST needs a second protocol for.
Warning
gRPC's browser gap is real: browsers can't speak native gRPC, so web frontends need gRPC-Web plus a translating proxy, or a REST/JSON gateway in front. If your primary consumer is a browser app, that extra hop erases much of gRPC's simplicity advantage, budget for it or stay with REST at the edge.
Verdict
This is less either/or than most comparisons: the common winning pattern is REST (or JSON over HTTP) at the edge, where universality, caching, and debuggability matter, and gRPC between internal services, where type safety, streaming, and per-call efficiency compound across a microservice fleet. Choose gRPC when you control both ends of the connection; choose REST when you don't.