gRPC

On this page 7

gRPC is an open-source remote procedure call framework that lets a client call methods on a server as if they were local functions, using Protocol Buffers to define the service contract and HTTP/2 as the transport. Among APIs, it represents the contract-first, strongly typed approach, in which client and server code is generated from one schema file.

Originally developed at Google from its internal Stubby system and now hosted by the Cloud Native Computing Foundation, gRPC is widely used for service-to-service communication in microservice architectures, mobile backends and low-latency systems. Its main advantages are compact binary messages, streaming and generated stubs in more than ten languages; its main costs are weaker browser support and less human-readable traffic.

How gRPC works

A gRPC API starts with a .proto file that declares services, methods and message types. The protoc compiler with language plugins generates a client stub that exposes each method as a function and a server skeleton that developers implement. Calling the stub serializes the request message, sends it to the server and deserializes the response.

On the wire, each call is an HTTP/2 stream. The method is encoded in the path, for example /inventory.v1.StockService/GetItem, metadata travels as HTTP/2 headers, and each message is sent as a length-prefixed binary frame. The call ends with trailers that carry a gRPC status code and an optional message, separate from the HTTP status.

Because HTTP/2 multiplexes many streams over one TCP connection, a client can run hundreds of concurrent calls without opening new connections, and header compression with HPACK reduces repeated metadata overhead. Long-lived connections also mean that load balancing must happen per request rather than per connection, a point that often surprises teams.

The four gRPC call types

gRPC defines four interaction patterns, declared in the .proto file with the stream keyword on the request, the response or both. Streaming is a first-class feature rather than an add-on, which distinguishes gRPC from most request-response API styles.

Call typeClient sendsServer returnsTypical use
UnaryOne messageOne messageLookups, commands, most CRUD calls
Server streamingOne messageA stream of messagesLive price feeds, large result sets
Client streamingA stream of messagesOne messageUploading telemetry or file chunks
Bidirectional streamingA streamA streamChat, collaborative editing, real-time control
gRPC method types

Every call can carry a deadline, an absolute time after which the client abandons it and the server receives a cancellation. Deadlines propagate through chains of services, which prevents a slow downstream dependency from tying up resources across the whole system.

gRPC compared with other API styles

gRPC competes with REST APIs, GraphQL and JSON-RPC, and the right choice depends on who the clients are and how tightly they are coupled to the server. The table contrasts the main properties.

PropertygRPCREST APIGraphQLJSON-RPC
ContractProtocol Buffers, mandatoryOptional, often OpenAPISchema, mandatoryInformal or custom
Payload formatBinaryUsually JSONJSONJSON
TransportHTTP/2HTTP/1.1 or laterUsually HTTPAny transport
StreamingNative, both directionsLimited, via SSE or chunkingSubscriptionsNot standardized
Browser supportNeeds gRPC-Web proxyNativeNativeNative
CachingNo HTTP cachingStrong HTTP cachingMostly client-sideNone
gRPC versus related API styles

A frequent architecture therefore uses gRPC internally and REST or GraphQL at the edge. Gateways such as gRPC-Gateway or Envoy transcoding can expose a JSON interface generated from the same .proto definitions, so one contract serves both audiences.

Designing and evolving gRPC services

Protocol Buffers identify fields by numeric tags, not names, and this rule governs safe schema evolution. Adding a new field with a new tag is backward compatible, because older clients simply ignore unknown fields. Changing a tag number or a field type breaks every existing client.

  • Never reuse a deleted field number; mark it with reserved so it cannot return by accident.
  • Version packages explicitly, such as payments.v1 and payments.v2, for breaking changes.
  • Wrap requests and responses in dedicated messages, even for one field, so they can grow later.
  • Return rich errors through the standard status codes and detail messages rather than custom flags.
  • Lint and check compatibility of .proto files in continuous integration before merging.

Operational features matter as much as the schema. Production deployments typically enable TLS or mutual TLS, server reflection for debugging tools, the standard health checking protocol and interceptors, the gRPC equivalent of middleware, for authentication, logging and metrics.

Limitations and common pitfalls

gRPC removes many integration problems but introduces its own operational traps. The table lists the ones experienced teams report most often.

ProblemCauseMitigation
One backend instance overloadedConnection-level load balancing with long-lived HTTP/2Client-side or proxy request-level balancing
Calls hang during outagesNo deadline set on the clientSet deadlines on every call
Browser cannot call the serviceBrowsers lack low-level HTTP/2 controlgRPC-Web with a proxy
Hard to inspect trafficBinary payloadsReflection-aware tools such as grpcurl
Memory errors on large payloadsDefault message size limit of about 4 MBStream data in chunks instead
Typical gRPC problems

gRPC is a weak fit for public APIs consumed by unknown third parties, where JSON over HTTP remains easier to adopt, document and cache. It is a strong fit where both ends are controlled and latency, throughput and type safety dominate the requirements.

Put simply

gRPC is a way for two programs to talk to each other as if one were calling a function inside the other. This works even when they run on different machines. Both sides first agree on a precise menu of what can be asked and what each answer looks like.

Messages travel in a compact form that computers read quickly. They are not plain readable text. The result is fast, reliable conversation between services built by teams that share the same menu. People do need special tools to read the messages.

In practice

A food delivery platform runs about forty internal services. The order service must check stock with the inventory service, price the basket with the pricing service and request a courier from the dispatch service, all within a target of 200 milliseconds for the customer.

The teams define each service in .proto files stored in a shared repository, generate Go and Kotlin clients, and set a 150 millisecond deadline on the order flow that propagates to every downstream call. Courier positions are pushed to the order tracker through server streaming instead of polling. Internal call latency becomes predictable, and breaking contract changes are caught in continuous integration before deployment, while the public mobile API remains a REST interface served by a gateway.