What Is gRPC?

gRPC (Google Remote Procedure Call) is a high-performance RPC framework developed by Google. It uses HTTP/2 for transport, Protocol Buffers (protobuf) for serialization, and provides features like bidirectional streaming, flow control, and built-in authentication.

gRPC vs. REST

FeatureRESTgRPC
ProtocolHTTP/1.1 or HTTP/2HTTP/2 only
FormatJSON (text)Protobuf (binary)
ContractOptional (OpenAPI)Required (.proto files)
StreamingLimited (WebSocket)Built-in (4 patterns)
Code generationOptionalBuilt-in
Browser supportNativeRequires gRPC-Web
PerformanceGoodExcellent (2-10x faster)
Use casePublic APIs, webMicroservices, mobile

When to Use gRPC

gRPC excels in:

  • Microservice-to-microservice communication (internal APIs)
  • Low-latency, high-throughput systems
  • Polyglot environments (auto-generates clients in 10+ languages)
  • Streaming use cases (real-time data, chat, video)

Protocol Buffers

Protocol Buffers (protobuf) define the data structures and service interfaces. A .proto file serves as the API contract:

syntax = "proto3";

package user;

service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc ListUsers (ListUsersRequest) returns (ListUsersResponse);
  rpc CreateUser (CreateUserRequest) returns (User);
  rpc StreamUpdates (StreamRequest) returns (stream UserUpdate);
}

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
  Role role = 4;
}

enum Role {
  UNKNOWN = 0;
  ADMIN = 1;
  USER = 2;
  VIEWER = 3;
}

message GetUserRequest {
  int32 id = 1;
}

message CreateUserRequest {
  string name = 1;
  string email = 2;
  Role role = 3;
}

Key Protobuf Concepts

  • Field numbers (1, 2, 3) are used in the binary format — never change them
  • Default values — empty strings, zero, false (no null concept)
  • Backward compatibility — add new fields with new numbers, never remove old ones
  • Nested messages — messages can contain other messages

gRPC Communication Patterns

Unary RPC (Request-Response)

Like a regular REST call — one request, one response:

Client → GetUser(id: 42) → Server
Client ← User{name: "Alice"} ← Server

Server Streaming

Server sends a stream of responses to a single client request:

Client → ListUsers(filter: "active") → Server
Client ← User{name: "Alice"} ← Server
Client ← User{name: "Bob"} ← Server
Client ← User{name: "Charlie"} ← Server
Client ← [stream end] ← Server

Client Streaming

Client sends a stream of requests, server responds once:

Client → CreateUser{name: "Alice"} → Server
Client → CreateUser{name: "Bob"} → Server
Client → CreateUser{name: "Charlie"} → Server
Client → [stream end] → Server
Client ← BatchResult{created: 3} ← Server

Bidirectional Streaming

Both client and server stream simultaneously:

Client ↔ Server (messages flow both directions independently)

Testing gRPC Services

Using grpcurl

grpcurl is the cURL equivalent for gRPC:

# Install
brew install grpcurl  # macOS
# or
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest

# List services
grpcurl -plaintext localhost:50051 list

# Describe a service
grpcurl -plaintext localhost:50051 describe user.UserService

# Call a method
grpcurl -plaintext -d '{"id": 42}' \
  localhost:50051 user.UserService/GetUser

# Call with metadata (headers)
grpcurl -plaintext \
  -H "Authorization: Bearer token123" \
  -d '{"name": "Alice", "email": "alice@example.com"}' \
  localhost:50051 user.UserService/CreateUser

Using Postman

Postman supports gRPC testing since 2022:

  1. Create a new gRPC request
  2. Enter the server URL
  3. Import the .proto file or use server reflection
  4. Select the method and enter the message
  5. Click Invoke

Testing gRPC with Python

import grpc
import user_pb2
import user_pb2_grpc

# Connect to server
channel = grpc.insecure_channel('localhost:50051')
stub = user_pb2_grpc.UserServiceStub(channel)

# Unary call
request = user_pb2.GetUserRequest(id=42)
response = stub.GetUser(request)
assert response.name == "Alice"
assert response.email == "alice@example.com"

# Server streaming
request = user_pb2.ListUsersRequest()
for user in stub.ListUsers(request):
    print(f"User: {user.name}")

gRPC-Specific Test Scenarios

Error Handling (gRPC Status Codes)

gRPC uses its own status codes instead of HTTP status codes:

gRPC CodeHTTP EquivalentMeaning
OK (0)200Success
INVALID_ARGUMENT (3)400Bad request
NOT_FOUND (5)404Resource not found
ALREADY_EXISTS (6)409Conflict
PERMISSION_DENIED (7)403Forbidden
UNAUTHENTICATED (16)401Unauthorized
INTERNAL (13)500Server error
UNAVAILABLE (14)503Service unavailable

Streaming Tests

TestWhat to Verify
Server stream cancellationClient can cancel mid-stream
Empty streamServer returns zero messages gracefully
Large streamPerformance with thousands of messages
Stream error mid-wayProper error handling on both sides
Timeout on streamDeadline exceeded after configured timeout

Deadline/Timeout Testing

gRPC has built-in deadline support:

# Set a 5-second deadline
response = stub.GetUser(request, timeout=5.0)

Test that the server properly handles expired deadlines with DEADLINE_EXCEEDED status.

Hands-On Exercise

  1. Set up grpcurl: Install grpcurl and use it to explore a public gRPC service or a local one.
  2. Test all patterns: If you have access to a gRPC service, test unary, server streaming, and error scenarios.
  3. Compare with REST: Call the same operation via gRPC and REST equivalent. Compare response size and time.
  4. Error testing: Send requests with invalid protobuf messages, missing required fields, and invalid enum values.

Key Takeaways

  • gRPC uses HTTP/2 and Protocol Buffers for high-performance microservice communication
  • Proto files define the strict API contract — all clients and servers must conform to the same schema
  • Four communication patterns: unary, server streaming, client streaming, and bidirectional streaming
  • gRPC has its own status codes (NOT_FOUND, INVALID_ARGUMENT) distinct from HTTP codes
  • grpcurl is the essential command-line tool for gRPC testing, equivalent to cURL for REST