Choosing between gRPC and REST is a fundamental API design decision with significant implications for performance, developer experience, and interoperability. REST (Representational State Transfer) uses HTTP/1.1 with JSON and has been the dominant API style for public-facing APIs since 2010. gRPC uses HTTP/2 with Protocol Buffers (binary serialization) and has become the standard for internal microservice communication at Google, Netflix, and most large-scale systems. Understanding the trade-offs is essential for system design interviews.
Protocol and Serialization
REST uses HTTP/1.1 (one request per TCP connection in HTTP/1.1, multiplexed in HTTP/2) with JSON text serialization. JSON is human-readable, easy to debug, and universally supported. gRPC uses HTTP/2 exclusively, enabling multiplexed bidirectional streams over a single TCP connection. It serializes messages with Protocol Buffers (Protobuf): a binary format that is 3-10x smaller than equivalent JSON and 5-10x faster to serialize/deserialize. For a service making 10,000 RPC calls/second, Protobuf serialization savings are significant.
// Protocol Buffer definition (service contract)
syntax = "proto3";
service OrderService {
rpc CreateOrder (CreateOrderRequest) returns (Order);
rpc StreamOrderUpdates (OrderID) returns (stream OrderUpdate);
rpc BatchCreateOrders (stream CreateOrderRequest) returns (BatchResult);
}
message CreateOrderRequest {
string customer_id = 1;
repeated OrderItem items = 2;
string idempotency_key = 3;
}
message Order {
string id = 1;
OrderStatus status = 2;
google.protobuf.Timestamp created_at = 3;
double total_amount = 4;
}
Streaming Capabilities
gRPC supports four communication patterns: Unary RPC (one request, one response — like REST), Server streaming (one request, stream of responses — live updates, large result sets), Client streaming (stream of requests, one response — bulk upload), and Bidirectional streaming (both sides stream simultaneously — real-time collaboration, gaming, live chat). REST with HTTP/1.1 only supports unary. REST with HTTP/2 supports server-sent events (one-way streaming). WebSockets support bidirectional but lack the structured RPC model.
Schema-First vs. Schema-Optional
gRPC is schema-first: define the service contract in a .proto file, then generate client and server stubs in any supported language (Go, Java, Python, Node.js, C++, Rust). The schema is the single source of truth. Breaking changes are caught at compile time — a field removed from a proto definition fails to compile in dependent services. REST with JSON is schema-optional: OpenAPI specifications exist but are often not enforced. This makes gRPC significantly safer for evolving APIs in large organizations where multiple teams own different services.
When to Use Each
Use REST when: the API is public-facing (browsers, third-party developers); you need human-readable payloads for easy debugging; you need cache-ability (HTTP caching works naturally with REST GET); the consumer ecosystem requires HTTP/JSON (mobile apps, JavaScript frontends). Use gRPC when: the API is internal (microservice-to-microservice); performance is critical (high throughput, low latency); you need bidirectional or server streaming; you want strong schema enforcement and generated clients; polyglot services need type-safe contracts.
Key Interview Discussion Points
- gRPC-Web: runs gRPC over HTTP/1.1 for browser clients (browsers cannot use raw HTTP/2 framing required by gRPC)
- Load balancing: REST is stateless and easy to load balance at L7; gRPC long-lived connections require L7 load balancing aware of HTTP/2 streams
- Error handling: gRPC has a richer status code system (14 codes) vs. HTTP status codes; both support structured error details
- Protobuf backward compatibility: add new fields with new field numbers; never reuse field numbers; old and new clients remain compatible
- GraphQL as a third option: when the client needs flexible query shapes and REST would require many endpoints or over-fetching