Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

gRPC & Protocol Buffers

High-performance communication for microservices

gRPC (gRPC Remote Procedure Calls) is a high-performance, open-source RPC framework developed by Google. It enables you to call remote functions as if they were local functions, abstracting away the complexity of network communication.

gRPC uses Protocol Buffers (protobuf) for serialization and HTTP/2 for transport. This combination provides significant performance advantages over traditional REST APIs using JSON over HTTP/1.1. The framework generates client and server code from .proto files, ensuring type safety and reducing boilerplate code.

Key Insight: gRPC is designed for inter-service communication in microservices architectures. It’s optimized for performance, with binary serialization reducing payload sizes by 50-70% compared to JSON, and HTTP/2 providing multiplexing and header compression.

Diagram
FeatureREST/JSONgRPC
SpeedSlower (text parsing)Faster (binary)
Payload SizeLarger (text)Smaller (binary)
StreamingLimitedFull support
Type SafetyRuntimeCompile-time
Code GenerationManualAutomatic
Browser SupportExcellentLimited

Protocol Buffers (protobuf) is a binary serialization format. Think of it as a more efficient alternative to JSON.

JSON (text-based):

{
"id": 12345,
"name": "John Doe",
"email": "[email protected]",
"age": 30
}

Size: ~80 bytes

Protocol Buffers (binary):

[encoded binary data]

Size: ~25 bytes (3x smaller!)

  1. Smaller size - No field names, just values
  2. Faster parsing - No string parsing
  3. Type safety - Schema enforces types
  4. Backward compatible - Can evolve schemas

.proto files define your service contract. They’re like API documentation + code generator input.

syntax = "proto3";
package user_service;
// Message definition (like a struct/class)
message User {
int32 id = 1;
string name = 2;
string email = 3;
int32 age = 4;
}
message GetUserRequest {
int32 user_id = 1;
}
message GetUserResponse {
User user = 1;
}
// Service definition
service UserService {
// Unary RPC: one request, one response
rpc GetUser(GetUserRequest) returns (GetUserResponse);
// Server streaming: one request, multiple responses
rpc ListUsers(GetUserRequest) returns (stream User);
// Client streaming: multiple requests, one response
rpc CreateUsers(stream User) returns (CreateUsersResponse);
// Bidirectional streaming: multiple requests, multiple responses
rpc ChatUsers(stream ChatMessage) returns (stream ChatMessage);
}

Field numbers (1, 2, 3…) are important:

  • Used for binary encoding (not field names!)
  • Must be unique within message
  • Once used, never change (backward compatibility)
  • Use 1-15 for frequently used fields (1 byte encoding)

Common types:

  • int32, int64 - Integers
  • float, double - Floating point
  • bool - Boolean
  • string - UTF-8 string
  • bytes - Raw bytes
  • repeated - Arrays/lists
  • map - Key-value pairs

One request, one response. Like a function call.

service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse);
}

Flow:

Client → Request → Server
Client ← Response ← Server

One request, multiple responses. Server sends stream of data.

service UserService {
rpc ListUsers(GetUserRequest) returns (stream User);
}

Flow:

Client → Request → Server
Client ← User 1 ← Server
Client ← User 2 ← Server
Client ← User 3 ← Server
...

Use cases:

  • Streaming search results
  • Real-time updates
  • Large dataset transfer

Multiple requests, one response. Client sends stream of data.

service UserService {
rpc CreateUsers(stream User) returns (CreateUsersResponse);
}

Flow:

Client → User 1 → Server
Client → User 2 → Server
Client → User 3 → Server
Client ← Response ← Server

Use cases:

  • Batch uploads
  • Collecting metrics
  • Aggregating data

Multiple requests, multiple responses. Both sides stream.

service ChatService {
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}

Flow:

Client → Message 1 → Server
Client ← Message 2 ← Server
Client → Message 3 → Server
Client ← Message 4 ← Server
...

Use cases:

  • Chat applications
  • Real-time collaboration
  • Interactive games

Diagram

gRPC uses status codes (similar to HTTP but different):

CodeMeaningHTTP Equivalent
OKSuccess200
INVALID_ARGUMENTBad request400
NOT_FOUNDResource not found404
ALREADY_EXISTSConflict409
PERMISSION_DENIEDForbidden403
UNAUTHENTICATEDUnauthorized401
RESOURCE_EXHAUSTEDRate limited429
INTERNALServer error500

Diagram
  • Microservices communication (internal APIs) - Perfect for service-to-service calls where performance matters
  • High-performance needs (low latency, high throughput) - 5-10x faster than REST/JSON
  • Streaming required (real-time data) - Built-in support for server, client, and bidirectional streaming
  • Strong typing needed (compile-time safety) - Protocol Buffers provide type safety at compile time
  • Polyglot environments (multiple languages) - Generate client/server code in any language from .proto files
  • Public APIs (browser support limited) - Browsers have limited gRPC support (gRPC-Web exists but adds complexity)
  • Simple CRUD (REST is simpler) - REST is easier to understand and debug for simple operations
  • Human-readable needed (JSON is better) - JSON is easier to read and debug than binary protobuf
  • Firewall restrictions (HTTP/2 may be blocked) - Some firewalls/proxies don’t support HTTP/2 properly

Diagram

Typical performance differences:

MetricREST/JSONgRPC
Latency10-50ms2-10ms
Throughput1K-10K req/s10K-100K req/s
Payload Size100%30-50%
CPU UsageHigherLower

Why gRPC is faster:

  1. Binary encoding (no JSON parsing)
  2. HTTP/2 (multiplexing, header compression)
  3. Connection reuse (less overhead)
  4. Efficient serialization (protobuf)

Diagram

At the code level, gRPC translates to service interfaces, message types, and streaming handlers.


Performance First

gRPC is 5-10x faster than REST due to binary encoding and HTTP/2. Perfect for microservices.

Streaming Support

gRPC supports four streaming types: unary, server, client, and bidirectional. REST can’t do this.

Strong Typing

Protocol Buffers provide compile-time type safety. Schema defines contract, code is generated.

Service Contracts

.proto files define service contracts. Generate client/server code in any language automatically.