gRPC
A high-performance, open-source RPC framework using Protocol Buffers and HTTP/2 — covering the four service types, generated stubs, gRPC-Web for browsers, load balancing challenges, and the health checking protocol.
What it is
gRPC (gRPC Remote Procedure Calls) is a high-performance, open-source RPC framework originally developed by Google and donated to the CNCF. It uses Protocol Buffers (Protobuf) as the Interface Definition Language (IDL) and serialisation format, and runs over HTTP/2, gaining multiplexed streams, header compression (HPACK), and binary framing.
You define services and message types in a .proto file. The protoc compiler generates strongly-typed client stubs and server skeletons in your language of choice (Go, Java, Python, C++, Node.js, Kotlin, Swift, and more). Callers invoke methods on the generated stub as if calling a local function; gRPC handles serialisation, connection management, retries, and metadata.
// user_service.proto
syntax = "proto3";
package users.v1;
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc ListUsers(ListUsersRequest) returns (stream User);
rpc UploadAvatars(stream UploadRequest) returns (UploadResponse);
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}
message GetUserRequest { string user_id = 1; }
message User {
string id = 1;
string name = 2;
string email = 3;
google.protobuf.Timestamp created_at = 4;
}
Why it exists
Google had been using a form of RPC internally (Stubby) for decades. As the industry moved toward microservices, the need for a fast, language-agnostic, contract-first inter-service communication protocol became clear. REST + JSON works, but JSON parsing is CPU-intensive, there is no codegen, and HTTP/1.1 imposes serialisation overhead. gRPC solves these: Protobuf is 3–10× smaller and faster to serialise/deserialise than JSON, and HTTP/2 multiplexing eliminates head-of-line blocking between concurrent requests on the same connection.
When to use
- Internal service-to-service communication in a microservices architecture where latency and throughput matter.
- Polyglot environments — gRPC generates idiomatic clients for 10+ languages from the same
.proto. - Real-time bidirectional streaming (e.g., live telemetry, collaborative editing, gaming).
- Mobile clients needing compact payloads on constrained networks.
- When you want strong schema enforcement enforced at compile time across teams.
When not to use
- Public APIs consumed by arbitrary clients — REST/JSON remains the universal baseline; gRPC requires generated stubs or a manually crafted HTTP/2 client.
- Browser-native calls without gRPC-Web or a transcoding proxy — browsers cannot use the raw gRPC protocol; gRPC-Web or Connect adds a compatibility layer but has limitations.
- Simple request/response over plain HTTP/1.1 infrastructure — if your proxy, load balancer, or API gateway doesn't understand HTTP/2, gRPC will not work or will require significant configuration.
- Human-readable debugging — Protobuf binary is not legible without tooling; REST JSON is immediately inspectable with curl.
Typical architecture
Four gRPC service types:
1. Unary RPC (request / response)
Client ──── GetUser(req) ────► Server
Client ◄─── User(resp) ────── Server
2. Server Streaming
Client ──── ListUsers(req) ──► Server
Client ◄─── User stream ───── Server (N messages)
Client ◄─── END ───────────── Server
3. Client Streaming
Client ──── Upload stream ───► Server (N messages)
Client ──── END ─────────────► Server
Client ◄─── UploadResponse ── Server
4. Bidirectional Streaming
Client ←──── ChatMessage stream ────► Server
(interleaved both ways)
Load balancing challenge:
L4 LB (TCP) → routes by connection, not request
→ all requests on one conn go to same pod
L7 LB (HTTP/2) → routes per RPC stream
→ requires HTTP/2-aware proxy (Envoy, Nginx, Traefik)
Client-side LB → stub resolves DNS, picks backend per call
→ needs service discovery integration
Health check protocol (grpc.health.v1):
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
Status: SERVING | NOT_SERVING | SERVICE_UNKNOWN
Pros and cons
Pros
- Protobuf serialisation is compact (binary) and fast — typically 3–10× smaller than equivalent JSON.
- HTTP/2 multiplexing: many concurrent RPCs over one TCP connection with no head-of-line blocking.
- Codegen from
.protoprovides type-safe clients in 10+ languages without manual SDK work. - Built-in streaming: four service types cover the full communication spectrum.
- Deadline/timeout propagation and cancellation are first-class primitives.
- Interceptor chains (server and client) enable cross-cutting concerns: auth, logging, tracing.
Cons
- Not browser-native: requires gRPC-Web proxy (Envoy) or Connect protocol adaptation.
- Binary protocol is hard to inspect without tooling (grpcurl, grpcui).
- HTTP/2 load balancing requires L7-aware proxies — L4 load balancers break per-RPC distribution.
- Proto schema changes must follow strict backward-compatibility rules (field numbers cannot be reused).
- Steeper learning curve than REST: requires understanding proto IDL, codegen pipeline, and HTTP/2.
- Some cloud API gateways and firewalls don't support HTTP/2 natively, requiring transcoding.
Implementation notes
Protocol Buffers field rules
Protobuf field numbers are permanent — once assigned, they can never be reused for a different field (even if the original is removed). Removing a field must be followed by reserving its number: reserved 3; and reserved "old_field";. Field numbers 1–15 are encoded in one byte; use them for frequently populated fields. Always default to optional fields in proto3 rather than required (proto3 removed required).
Deadlines and cancellation
Always set a deadline on the client stub: ctx, cancel := context.WithTimeout(ctx, 5*time.Second). gRPC propagates this deadline across chained service calls automatically. If the deadline expires, the server receives a cancellation signal and should abort in-flight work. Failing to set deadlines causes unbounded goroutine/thread accumulation under slow or stuck downstream services.
Interceptors
gRPC interceptors are middleware for both clients and servers. Use them for: authentication (validate JWT in server interceptor), distributed tracing (inject/extract trace context), metrics (record RPC duration, error rate), and logging. Interceptors chain compositionally — order matters for auth (first) before logging (second).
gRPC-Web for browsers
Browsers cannot use the native gRPC protocol over HTTP/2 due to lack of access to HTTP trailers. gRPC-Web is a variant that encodes trailers in the response body and works over HTTP/1.1 + XHR. It requires a proxy (typically Envoy) to translate gRPC-Web to native gRPC. The Connect protocol (by Buf) is a more modern alternative that works natively over HTTP/1.1 and HTTP/2 without a proxy, and is compatible with gRPC servers.
gRPC health checking protocol
The standard grpc.health.v1.Health service provides a Check unary RPC and a Watch server-streaming RPC. Kubernetes liveness and readiness probes can call this endpoint via grpc-health-probe. Register per-service health checks (using the service name as the key) in addition to the global "" key.
Reflection
Enable gRPC server reflection in development to allow tooling like grpcurl and grpcui to discover available services and call them without the .proto files. Disable reflection in production — it exposes your service contract to unauthenticated callers.
Common failure modes
- No deadline set — cascading slow service calls pile up threads/goroutines, exhausting the thread pool under load.
- L4 load balancer with persistent HTTP/2 connections — all traffic from a client pod routes to one server pod; new pods don't receive traffic until connections are re-established.
- Field number reuse — reusing a proto field number for a different field causes silent data corruption when old and new versions communicate.
- Ignoring gRPC status codes — treating all errors as generic failures instead of mapping
UNAVAILABLE,DEADLINE_EXCEEDED, andRESOURCE_EXHAUSTEDto appropriate retry/backoff logic. - Streaming without backpressure — a fast server-streaming RPC overwhelms a slow client; implement flow control using the stream's
Sendblocking behaviour.
Decision checklist
- Are deadlines set on all outbound gRPC calls?
- Is an L7-aware proxy (Envoy, Nginx with grpc_pass) handling load balancing?
- Are field numbers in
.protofiles reserved after field removal? - Is the gRPC health checking protocol implemented and wired to Kubernetes probes?
- Are interceptors used for auth, tracing, and metrics rather than inline code?
- For browser clients, is gRPC-Web or Connect configured with a transcoding proxy?
- Is server reflection disabled in production?
- Are proto files version-controlled and governed by a breaking-change lint check (buf lint)?
Example use cases
- Microservice internal communication — an order service calls the inventory service and payment service over gRPC with 100ms deadlines; Envoy sidecar handles mTLS and load balancing.
- Live telemetry streaming — IoT device agents use client-streaming gRPC to stream sensor readings at 100Hz; the server aggregates in a time-series database.
- ML model inference — TensorFlow Serving and Triton expose gRPC endpoints for prediction requests; Protobuf binary payloads for large tensors are 5× smaller than JSON equivalents.
- Bidirectional chat — a customer support platform uses bidirectional streaming gRPC to relay chat messages with sub-100ms latency between agent and customer.
Related patterns
- REST API Design — the JSON/HTTP alternative for public-facing APIs.
- GraphQL — flexible query language for client-driven data fetching.
- API Gateway — transcoding gRPC to REST/JSON for external consumers.
- API Authentication — mTLS for service-to-service identity in gRPC.
- Contract Testing — Protobuf schema compatibility testing with buf breaking.
Further reading
- gRPC official documentation — grpc.io/docs
- Buf schema registry and breaking-change detection — buf.build
- Connect protocol specification — connectrpc.com
- Google Cloud — gRPC vs REST: Understanding gRPC, OpenAPI and REST and when to use them.
- Envoy Proxy gRPC documentation — envoyproxy.io/docs/envoy/latest/intro/arch_overview/other_protocols/grpc
- Protocol Buffers Language Guide (proto3) — protobuf.dev/programming-guides/proto3