Lesson 9 · Errors, deadlines & metadata
Deadlines, timeouts & cancellation
The client sets the clock; the server — and everything downstream — honours it.
Your win: distinguish a deadline from a timeout, explain who sets it
and how it propagates through context, and describe cooperative cancellation.
(Builds on Go course Lesson 17.)
Deadline vs timeout
The client sets it; the server honours it
The client attaches a deadline to the call. gRPC sends it to the server, which
surfaces it on the handler's context.Context. When it passes, the call is
cancelled with DeadlineExceeded. Crucially: a server that is also a
client must forward the remaining deadline to its downstream calls — which
gRPC + context do automatically.
Our framework enforces a server-side deadline for you — an interceptor wraps every handler's context with a timeout:
internal/golibs/interceptors/timeout.go:14 · bootstrap/grpc.go:30// TimeoutUnaryServerInterceptor wraps each handler ctx (default 5s):
ctx, cancel := context.WithTimeout(ctx, cc.GRPC.HandlerTimeout) // defaultMaxTimeout = 5s
defer cancel()
return handler(ctx, req)
context.Context, our handlers pass that same
ctx to downstream gRPC clients (Lesson 1's InternalRetrieveMedia(ctx, …))
and to DB queries — so the whole call tree shares one budget. A per-method override
exists (HandlerTimeoutV2, -1 = bypass for slow endpoints), and
client dials add WithPerRetryTimeout (bootstrap/resource.go:386).
Cancellation is cooperative
When the client cancels (or the deadline passes, or a connection drops), the server's
ctx.Done() fires. Nothing is force-killed — a long-running handler must
check ctx and stop (exactly the cooperative model from Go L17). A
cancelled call ends with Canceled; our framework even remaps a raw "context
canceled" error to codes.Canceled (bootstrap/grpc.go:171).
ctx.Done() (e.g. a tight loop or a
non-context-aware library call) keeps running past the deadline. "The client's deadline
only helps if the server passes ctx down and checks it" is the nuance.
gRPC — Deadlines + Cancellation guides
The authoritative treatment of deadline propagation and cooperative cancellation. The "gRPC and Deadlines" blog post has great worked examples.
→ grpc.io/docs/guides/deadlines ·
/cancellation
→ grpc.io/blog/deadlines
Check yourself (from memory)
Q1. A gRPC deadline is…
Q2. Who sets the deadline for a call?
Q3. When the deadline passes, the call ends with…
DeadlineExceeded);
ctx.Done() fires so the handler can stop — cooperatively.
DeadlineExceeded).
In our repo a framework timeout interceptor wraps each handler's ctx with
context.WithTimeout (default 5s); because it rides context.Context,
the deadline propagates automatically to downstream gRPC calls and DB queries.
Cancellation is cooperative (Go L17) — long handlers must check ctx.Done().ctx.Deadline(), or see how retries
interact with a shrinking deadline? Ask me.