gRPC (Remote Procedure Call)

A high-performance microservice communication framework using Protocol Buffers and persistent HTTP/2 streams.

IntermediateAPI DesignChapter: API Design11 min read

The Concept

In web development, we are used to building REST APIs where servers exchange JSON text strings over separate HTTP requests. While JSON is human-readable, it is slow to serialize, takes up significant bandwidth, and lacks compile-time type verification.

gRPC is an alternative communication framework built specifically for internal microservices:

  1. Interface Definition Language (IDL): You write a simple schema contract file (.proto) defining the database methods, request parameters, and return types.
  2. Code Generation: A compiler (protoc) compiles that schema file into helper classes (stubs) in Go, Python, TypeScript, and other languages.
  3. HTTP/2 Transport: Data is serialized into a highly optimized binary format (Protocol Buffers) and streamed bidirectionally over a persistent HTTP/2 connection.

gRPC vs REST Comparison

gRPC (HTTP/2 + Protobuf) vs REST (HTTP/1.1 + JSON)

Traditional REST API Client

Server JSON Text HTTP/1.1 (Text)

gRPC Microservice Client Stub

Server Stub Protobuf Binary HTTP/2 (Multiplexed) Shared Schema Contract user.proto Generates Client Stubs Generates Server Stubs

Practical Analogy

Think of gRPC as calling a local function:

  • In standard REST APIs, if service A wants information from service B, it must convert data to a JSON string, write HTTP headers, route the payload, and parse the JSON string on the other side. This is like writing a formal, formatted letter and sending it through the mail post.
  • gRPC abstracts the network. Calling an API on a remote server looks and behaves exactly like calling a local function inside your own code: userService.getUser(id).
  • Under the hood, gRPC serializes data into tiny binary packages and streams them down a persistent pipeline (HTTP/2). It is like speaking directly to your colleague sitting at the desk next to you.

Protocol Buffers (Protobuf) Wire Format

Protocol Buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data.

Instead of sending text names like {"user_id": 42} where the field name "user_id" is repeated in every single payload, Protobuf assigns each field a small integer tag (e.g., user_id = 1). On the wire, only the tag, the type, and the raw binary value are sent. This makes payloads significantly smaller:

  • JSON Payload: {"id": 1001, "name": "Alice"} takes 31 bytes.
  • Protobuf Payload: 08 E9 07 12 05 41 6C 69 63 65 takes only 10 bytes (where 08 indicates tag 1 and type varint, E9 07 is the varint for 1001, 12 indicates tag 2 and type length-delimited, 05 is the string length, and the rest is the ASCII characters for "Alice").

The Four Streaming Modes

gRPC supports four distinct communication patterns, which are declared directly in the proto definition:

1. Unary RPC

The classic request-response model. The client sends a single request and receives a single response.

  • Use Case: Fetching a specific user record or submitting a form.
  • Proto syntax: rpc GetUser (UserRequest) returns (UserResponse);

2. Server Streaming RPC

The client sends one request, and the server returns a stream of multiple responses. The client reads from the stream until there are no more messages.

  • Use Case: Streaming a list of products, real-time stock price updates, or server logs.
  • Proto syntax: rpc ListUsers (ListRequest) returns (stream UserResponse);

3. Client Streaming RPC

The client writes a sequence of messages and sends them to the server. Once the client finishes writing, it waits for the server to read them and return a single response.

  • Use Case: Uploading a large file in chunks or sending a batch of telemetry data.
  • Proto syntax: rpc UploadMetrics (stream MetricRequest) returns (UploadSummary);

4. Bidirectional Streaming RPC

Both sides send a sequence of messages using a read-write stream. The two streams operate independently, meaning clients and servers can read and write in any order.

  • Use Case: Live chat applications, real-time gaming synchronization, or persistent duplex data sync.
  • Proto syntax: rpc ChatSession (stream ChatMessage) returns (stream ChatMessage);

Why it matters in Backend Systems

  1. Performance & Serialization Speed: Protocol Buffers serialize and parse up to 6x faster than JSON and occupy a fraction of the bandwidth, reducing CPU usage and network overhead in microservice grids.
  2. Strict Type Contracts: Since code stubs are generated from a shared .proto schema file, compile-time errors will trigger immediately if service A changes a payload parameter without informing service B.
  3. Streaming Support: gRPC natively supports streaming APIs (client-side streaming, server-side streaming, and full bidirectional streams) making it perfect for real-time dashboards, metrics, and chat pipelines.

Further Reading

Prerequisites

Code Examples