Working with Metadata

1. Creating Metadata

Example: Build MD

md := metadata.New(map[string]string{
    "x-request-id": "abc-123",
    "authorization": "Bearer " + token,
})
// or
md := metadata.Pairs("x-tenant", "acme", "x-region", "us-east-1")
RuleDetail
Keys lowercaseAuto-lowered; case-insensitive
Suffix -binBinary metadata (auto base64 over wire)
Reserved prefix grpc-Don't use for app metadata

2. Sending Metadata from Client

Example: Outgoing context

ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+tok)
res, err := client.GetUser(ctx, req)

3. Receiving Metadata on Server

Example: Read incoming MD

md, ok := metadata.FromIncomingContext(ctx)
if ok {
    if v := md.Get("authorization"); len(v) > 0 { token = v[0] }
}
APIReturns
FromIncomingContextMap of header values
md.Get("key")[]string (multiple values allowed)

4. Sending Headers from Server

APIDetail
grpc.SendHeader(ctx, md)Send before first response message
grpc.SetHeader(ctx, md)Merge with future Send

5. Sending Trailers from Server

APIDetail
grpc.SetTrailer(ctx, md)Sent after final message + status
UseSummary stats, total counts, request id echo

6. Receiving Headers on Client

Example: Capture headers

var header metadata.MD
res, err := client.GetUser(ctx, req, grpc.Header(&header))

7. Receiving Trailers on Client

Example: Capture trailers

var trailer metadata.MD
res, err := client.GetUser(ctx, req, grpc.Trailer(&trailer))
NoteDetail
Trailers always sentEven on error

8. Appending Metadata

APIDetail
md.Append(k, v...)Add to existing key
metadata.Join(md1, md2)Merge multiple MDs
AppendToOutgoingContextVariadic key/value pairs

9. Using Binary Metadata

Example: Binary key

md := metadata.Pairs("trace-context-bin", string(binData))
// Decoded on receiver as []byte

10. Forwarding Metadata

Example: Proxy metadata downstream

if md, ok := metadata.FromIncomingContext(ctx); ok {
    ctx = metadata.NewOutgoingContext(ctx, md.Copy())
}
res, err := downstream.Call(ctx, ...)
Best PracticeDetail
Filter sensitiveStrip authorization if downstream uses its own
Preserve tracingAlways forward traceparent, x-request-id