All scenes
Build a gRPC-style RPC framework
14 scenes · ~98 min · build the primitive
Build your own gRPC-style RPC framework
Every microservice talks over RPC, and the framework you ship determines half the system's failure modes. Build an RPC framework with codec, streams, deadlines, cancellation, retries, interceptors, and load-aware client-side balancing — and feel why gRPC ate the polyglot RPC market and why Thrift and JSON-over-HTTP linger.
- 01Calling a function on another machineA remote call is dressed up to look like a local one — but unlike a local call it can fail after the server already did the work, so the caller can't tell if it happened.~7 min
- 02TCP gives you bytes, not messagesTCP is a byte stream, not a message stream: two messages can arrive glued or split. A length prefix is what lets the receiver read exactly one message back.~7 min
- 03The schema: field numbers, not field namesA schema keys each field by a stable number, not its name — so an old reader can skip a field it doesn't know and still decode the rest. Never reuse a field number.~7 min
- 04One RPC, one stream, one pipe for manyHTTP/2 multiplexes many independent streams over one long-lived TCP connection; gRPC maps one RPC to one stream. A hundred calls share one pipe, not a hundred sockets.~7 min
- 05Four call shapes from one streamUnary and the three streaming shapes are the same stream — only the number and direction of DATA frames differ. Streaming is a consequence of the transport, not a bolt-on.~7 min
- 06Deadlines, not timeoutsA timeout is relative and resets each hop; a deadline is absolute and propagates the time remaining — so a downstream service never works for a caller that already gave up.~7 min
- 06aCancellation: an event, not a clockA deadline fires from a clock; cancellation fires from an event. Both ride one Context object down the chain, so aborting a parent stops all the doomed downstream work.~7 min
- 07Retries: idempotency and a token budgetOnly an idempotent method is safe to auto-retry, and even then a token-bucket budget must cap retries — or a brownout turns into a self-sustaining retry storm.~7 min
- 08Interceptors: the middleware onionAn interceptor wraps every call as one composable layer, so auth, metrics, tracing, and the retry policy are written once around the handler instead of per method.~7 min
- 09The L4 pinning trap: balance requests, not connectionsHTTP/2's one long-lived connection means an L4 load balancer pins every RPC to one backend. Client-side balancing discovers all backends and picks one per request.~7 min
- 10Flow control: a slow reader slows the writerThe receiver advertises a window of credit; the sender may only send DATA up to it. A slow reader stops granting credit, so the producer pauses instead of OOMing.~7 min
- 10aHead-of-line blocking and the QUIC fixHTTP/2 fixed app-layer head-of-line blocking, but all streams share one in-order TCP pipe, so one lost packet stalls them all. QUIC moves streams below the loss boundary.~7 min
- 11mTLS and propagating identityTLS encrypts and proves the server; mTLS proves both peers with a workload identity. The original caller's identity must propagate across hops, just like a deadline.~7 min
- 12Design canvas: configure the RPC stackPick codec, transport, deadline, retry, balancing, and security for four named workloads — each defended by the scene that taught it. gRPC inside the fleet, REST at the edge.~7 min