protocol

gRPC as a Transport

A binary contract-first RPC protocol over HTTP/2 — efficient and strongly typed for internal service-to-service calls, awkward at the browser edge.

grpcprotobufhttp2internal-apisubercontracts

Definition

gRPC defines services and messages in a schema, generates client and server code in many languages, and transports binary-encoded messages over HTTP/2 with multiplexed streams.

Where it wins

  • Internal service-to-service calls in a polyglot estate. The generated client removes an entire category of integration bug, and the schema is the contract rather than a document describing one.
  • Payload efficiency. Binary encoding is substantially smaller than JSON, which matters at high call volume and on constrained networks.
  • Streaming. Server, client and bidirectional streaming are first-class, not bolted on.
  • Contract evolution with real rules. Field numbers, reserved fields and clear compatibility semantics make additive change safe and breaking change obvious.

Large polyglot estates — Uber-scale service counts across several languages — adopt it substantially for the generated-client property. When thousands of services call each other, hand-written clients per language per service is not a maintenance burden anyone survives, and the schema registry becomes the organisation's actual API documentation.

Where it is awkward

  • Browsers. Browsers cannot speak gRPC natively; a proxy translation layer is required. For a public API consumed by web clients, this is friction with little payoff.
  • Debuggability. You cannot read a binary payload in a log or reproduce a call with curl without tooling. Teams underestimate how much day-to-day productivity comes from that.
  • Third-party integration. Partners expect REST and JSON. Offering gRPC externally narrows your integrator pool.
  • Load balancing. Long-lived HTTP/2 connections multiplex many requests, so connection-level layer 4 balancing pins all of a client's calls to one backend. Request-level (layer 7) balancing or client-side balancing is required, and getting this wrong produces badly skewed backend load that is easy to miss.

Failure scenarios

  • Layer 4 balancing in front of gRPC, so backends are unevenly loaded and adding instances does not help.
  • Breaking schema change — reusing a field number, changing a type — which fails at runtime rather than at compile time for already-deployed clients.
  • Deadlines not propagated, losing the main resilience benefit the protocol offers.
  • Adopted for a public API and then wrapped in a REST gateway anyway, paying both costs.

Trade-offs

Bought: type safety, efficiency, streaming, generated clients, disciplined contract evolution. Sold: human readability, browser compatibility, ease of ad-hoc debugging, and simplicity of load balancing.

The common and correct outcome: gRPC internally, REST and JSON at the public edge.

Interview question

"You put a layer 4 load balancer in front of a gRPC service and one backend receives most of the traffic. Why?"