# Low Level Design: gRPC vs REST — When to Use Each

Source: https://www.techinterview.org/post/3233474033/lld-grpc-vs-rest-api-design/
Updated: 2026-04-18 · techinterview.org

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
