Lesson 10 · Errors, deadlines & metadata
Metadata: headers in & out
How the auth token and trace ride the request — gRPC's version of headers.
Your win: explain what metadata is, read/write it in Go, and trace how our auth token becomes a handler's identity — the synchronous cousin of the Kafka header propagation you already learned.
Metadata = headers, separate from the message
Metadata is a set of key–value pairs sent alongside a
request or response — not part of the message body. It carries the auth token, a
request id, tracing context. Under the hood it's literally HTTP/2 headers:
keys are ASCII & case-insensitive, must not start with the reserved grpc-
prefix, and binary values use a -bin suffix.1
Reading & writing it in Go
// server: read incoming metadata
md, ok := metadata.FromIncomingContext(ctx)
token := md.Get("token")
// client: attach outgoing metadata
ctx = metadata.AppendToOutgoingContext(ctx, "token", jwt)
// or metadata.NewOutgoingContext(ctx, md)
The metadata → context bridge (our auth)
This is the move to internalise: the auth interceptor reads the token from
metadata, verifies the JWT, and injects the resulting claims into
context — so handlers read identity from ctx, never from metadata or
the request:
md, _ := metadata.FromIncomingContext(ctx)
token := md.Get("token") // metadata (the header)
// …verify JWT…
ctx = interceptors.ContextWithJWTClaims(ctx, claims) // context (Part 4 / Go L17)
Authorization header →
token metadata (gateway.WithMetadata). On the way out,
when a service calls downstream, UnaryClientAttachHeaderInterceptor
(bootstrap/resource.go:364) copies token/
pkg/version from the incoming metadata onto the outgoing call —
so identity travels the whole call chain.
gRPC — Metadata guide + grpc-go metadata doc
What metadata is, header vs trailer, and the Go metadata API for reading
incoming and setting outgoing.
Check yourself (from memory)
Q1. gRPC metadata is transmitted as…
Q2. A server reads incoming metadata with…
FromIncomingContext on the server;
NewOutgoingContext/AppendToOutgoingContext on the client.
Q3. In our services, the auth interceptor reads which header?
token, verifies the JWT, and
injects claims into context — the metadata→context bridge.
metadata.FromIncomingContext(ctx); client sets it via
metadata.NewOutgoingContext/AppendToOutgoingContext. Our auth
interceptor reads the token header, verifies the JWT, and injects claims
into context; downstream calls copy token/pkg/version
outward via UnaryClientAttachHeaderInterceptor. Parallel: Kafka propagates
claims/trace across an async boundary via message headers — gRPC metadata is the
synchronous cousin.