gRPC is Google’s RPC framework. It uses Protocol Buffers (Protobuf) for the message format and HTTP/2 as the transport.
In simple language: instead of POST /users with JSON, we call a typed function userService.GetUser(id) and get a typed response. The wire format is binary and small. The transport is HTTP/2 streams, so we get multiplexing for free.
Why It Exists
REST + JSON works great for browsers. For service-to-service traffic in a microservices system, it has problems:
- JSON is bulky and slow to parse.
- Schemas are documented in wikis, not enforced.
- Streaming is awkward.
gRPC fixes all three: tight binary encoding, schemas in .proto files, native streaming.
Protobuf Schema
We define services and messages in a .proto file:
syntax = "proto3";
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc ListUsers(ListUsersRequest) returns (stream User);
rpc UploadAvatars(stream AvatarChunk) returns (UploadResult);
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}
message GetUserRequest {
int64 id = 1;
}
message User {
int64 id = 1;
string name = 2;
string email = 3;
}
The protoc compiler generates client and server stubs in our language of choice. Both sides are statically typed against the same schema.
The Four Call Types
gRPC supports four kinds of RPCs, all built on HTTP/2 streams.
1. Unary
client ──req──> server
client <──res── server
(Like a normal function call)
2. Server streaming
client ──req──> server
client <──res── server
client <──res── server
client <──res── server
(Server sends many responses for one request)
3. Client streaming
client ──req──> server
client ──req──> server
client ──req──> server
client <──res── server
(Client sends many requests, gets one response)
4. Bidirectional streaming
client ──msg──> server
client <──msg── server
client ──msg──> server
client <──msg── server
(Both ends send independently)
Each direction maps to one HTTP/2 stream. Bidi streams are full-duplex.
HTTP/2 Streams as the Substrate
A gRPC call is just an HTTP/2 stream with a specific encoding:
- Method is always
POST. - Path is
/<service>/<method>(e.g.,/UserService/GetUser). - Body is length-prefixed Protobuf frames.
- Trailers carry the gRPC status code.
Because HTTP/2 multiplexes streams over a single TCP connection, hundreds of concurrent gRPC calls share one connection — no head-of-line blocking at the application layer.
gRPC vs REST
| Aspect | gRPC | REST + JSON |
|---|---|---|
| Wire format | Protobuf (binary) | JSON (text) |
| Schema | Enforced via .proto | Optional (OpenAPI) |
| Streaming | First-class, four flavors | Workarounds (SSE, WS) |
| Browser support | Needs gRPC-Web proxy | Native |
| Caching by CDNs | Hard (POST, binary body) | Native (GET, ETag) |
| Tooling for humans | Needs grpcurl/Bloomrpc | curl, browser, Postman |
| Transport | HTTP/2 only | Any HTTP |
| Speed | Faster (binary, multiplexed) | Slower |
Rule of thumb: gRPC for backend-to-backend, REST/GraphQL for client-to-backend.
A Quick Server (Node)
import grpc from "@grpc/grpc-js";
import protoLoader from "@grpc/proto-loader";
const pkg = grpc.loadPackageDefinition(
protoLoader.loadSync("user.proto")
);
const server = new grpc.Server();
server.addService(pkg.UserService.service, {
GetUser: (call, callback) => {
callback(null, { id: call.request.id, name: "Manish", email: "m@x.com" });
},
ListUsers: (call) => {
// Server streaming
for (const user of getAllUsers()) call.write(user);
call.end();
},
});
server.bindAsync("0.0.0.0:50051", grpc.ServerCredentials.createInsecure(), () => {});
Common Gotchas
- Browser support. Browsers can’t speak raw gRPC. We need gRPC-Web (an Envoy/Connect proxy translates).
- Load balancing. Standard L4 load balancers can’t see individual streams. Use L7 LBs (Envoy, Linkerd, gRPC-aware ingress).
- Debugging. No
curlmagic. Usegrpcurl, server reflection, or generated clients. - Versioning. Protobuf field numbers are forever. Adding fields is safe; removing/renumbering breaks old clients.
Interview Tip
If asked “why would we use gRPC over REST,” lead with three reasons: schema enforcement, performance (binary + HTTP/2 multiplexing), and first-class streaming. Mention that it’s not a great fit for browser clients without gRPC-Web — that nuance shows depth.