gRPC (gRPC)
REST APIs are like ordering at a restaurant by filling out a paper form and waiting for a tray to come back. gRPC is like calling the kitchen directly on a phone: you say what you want in a compressed shorthand, the kitchen processes it instantly, and you can even have a back-and-forth conversation on the same call. gRPC is faster, more structured, and designed for internal service-to-service communication where performance matters more than human readability.
gRPC (Google Remote Procedure Call) is an open-source, high-performance RPC framework developed by Google. It uses Protocol Buffers (protobuf) as its interface definition language and wire format, and runs over HTTP/2.
How it differs from REST:
| Dimension | REST | gRPC |
|---|---|---|
| Protocol | HTTP/1.1 or HTTP/2 | HTTP/2 (required) |
| Data format | JSON (text) | Protobuf (binary) |
| Schema | Optional (OpenAPI) | Mandatory (.proto file) |
| Code generation | Manual or OpenAPI codegen | Built-in from .proto |
| Streaming | No native support | Bidirectional streaming |
| Browser support | Native | Requires grpc-web proxy |
The four RPC types:
- Unary: one request, one response (like a REST call)
- Server-streaming: one request, stream of responses (e.g., log tailing)
- Client-streaming: stream of requests, one response (e.g., file upload)
- Bidirectional streaming: full-duplex, both sides stream simultaneously (e.g., chat, telemetry)
Protocol Buffers (.proto): Strongly-typed schema compiled to language-specific code. The compiler generates both client stubs and server interfaces. Schema changes are backward-compatible if field numbers are never reused.
HTTP/2 multiplexing: Multiple concurrent RPC calls share a single TCP connection via independent streams. No head-of-line blocking (unlike HTTP/1.1). Header compression via HPACK reduces overhead for small messages.
gRPC metadata: Key-value pairs sent in HTTP/2 headers, analogous to REST headers. Used for authentication tokens, request tracing IDs, and deadlines.
gRPC service definition and server implementation
// service.proto -- defines the contract for both client and server
syntax = "proto3";
package network;
service NetworkTools {
rpc CheckPort (PortRequest) returns (PortResponse);
rpc StreamLogs (LogRequest) returns (stream LogEntry);
}
message PortRequest {
string host = 1;
int32 port = 2;
}
message PortResponse {
bool open = 1;
string message = 2;
}
message LogRequest { string service = 1; }
message LogEntry { string line = 1; int64 timestamp = 2; }# Generate Go server and client stubs from the .proto file
$ protoc --go_out=. --go-grpc_out=. service.proto
# Use grpcurl (curl for gRPC) to call a running service
$ grpcurl -plaintext localhost:50051 list
network.NetworkTools
$ grpcurl -plaintext -d '{"host":"example.com","port":443}' \
localhost:50051 network.NetworkTools/CheckPort
{
"open": true,
"message": "Port 443 on example.com is OPEN"
}
# Enable gRPC server reflection for grpcurl to work without .proto
# (Go example in server setup)
# grpc_reflection_v1alpha.RegisterServerReflectionServer(s, reflection.NewServer(s)) gRPC powers Kubernetes internals, Google Cloud APIs, and most large-scale microservice platforms. Whenever you use kubectl, it speaks gRPC to the API server. Netflix, Square, and Lyft run gRPC at the core of their service mesh. The primary limitation is browser support: browsers cannot speak HTTP/2 at the frame level that gRPC requires, so browser-facing APIs still use REST or GraphQL, with gRPC reserved for backend-to-backend calls. The Envoy proxy and gRPC-Web bridge this gap. For new microservice projects, gRPC offers roughly 5-10x lower latency and 60-80% smaller payload size compared to JSON/REST, at the cost of requiring tooling to inspect binary traffic. Always enable TLS (mTLS in service meshes) and use deadlines on every RPC call to prevent cascading failures from stalled upstream services.