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

message = the WHAT (SendEmailRequest fields) metadata = the ABOUT-THIS-CALL (token, x-request-id, trace) — rides in HTTP/2 headers

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:

internal/usermgmt/pkg/interceptors/auth.go:124
md, _ := metadata.FromIncomingContext(ctx)
token := md.Get("token")          // metadata (the header)
// …verify JWT…
ctx = interceptors.ContextWithJWTClaims(ctx, claims)  // context (Part 4 / Go L17)
Anchor — propagation, in and out On the way in, the gateway maps the HTTP 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.
The parallel to lock in Recall the Kafka course: claims & trace propagate across an async boundary via Kafka message headers. gRPC metadata is the synchronous cousin — same idea (identity/trace travel with the call, outside the payload), different transport. Recognising that pattern once means you understand both.
Read this next

gRPC — Metadata guide + grpc-go metadata doc

What metadata is, header vs trailer, and the Go metadata API for reading incoming and setting outgoing.

grpc.io/docs/guides/metadata
grpc-go — metadata

Check yourself (from memory)

Q1. gRPC metadata is transmitted as…

Metadata rides in HTTP/2 headers (and trailers) — alongside, not inside, the message.

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?

It reads token, verifies the JWT, and injects claims into context — the metadata→context bridge.
What is gRPC metadata, how does our auth use it, and what's the Kafka parallel?
recall, then click to reveal
Metadata = key-value HEADERS sent alongside a request/response (over HTTP/2), separate from the message body — for auth token, request-id, trace. Server reads it via 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.
🎓 That's Part 3 Status codes, deadlines & cancellation, and metadata — the cross-cutting concerns every call carries. Part 4 is where they come together: interceptors, the middleware that reads that metadata, enforces those deadlines, and shapes those statuses.
Ready for Part 4 (interceptors, middleware & auth), or a mixed quiz across Lessons 8–10 first? Ask me.

1. gRPC — Metadata; grpc-go metadata doc.