gRPC Best Practices
Versioning protos, deadlines, and load-balancing gRPC in K8s.
Search across all documentation pages
Versioning protos, deadlines, and load-balancing gRPC in K8s.
These rules keep contracts stable, RPCs observable, and rollouts safe from laptop through production clusters.
buf breaking (or equivalent) in CI before merging .proto edits.bufconn..proto files.v1, v2) for incompatible API changes. Run dual servers or dual RPCs during migration windows.go_package and Java package options stable. Moving generated import paths breaks downstream modules silently.optional or FieldMask for partial updates. Distinguish unset fields from intentional zero values.Unimplemented<Service>Server on every service struct. Forward compatibility when RPCs are added.status.Error with the closest standard code. Reserve Internal for true bugs, not validation failures.ErrorInfo, BadRequest) for machine-readable errors. Gateways and clients can branch without string parsing.context cancellation in long handlers and stream loops. Stop work when clients disconnect.Unavailable with backoff and jitter. Avoid retry storms during outages.grpc.ClientConn across requests. Dialing per RPC wastes TCP and TLS handshakes.GracefulStop on servers.traceparent or OTel carriers). Pair with otelgrpc handlers for spans.insecure credentials are for local dev only.Internal with logged stack traces.io.EOF as normal stream end, not always as error. Return appropriate status on failure paths only.grpc.health.v1 and wire liveness/readiness probes. Set NOT_SERVING until dependencies are warm.GracefulStop on SIGTERM with a bounded Stop fallback. Match pod terminationGracePeriodSeconds.Client deadlines on every RPC.
They prevent cascading latency and make cancellation observable.
On every PR touching .proto files.
Treat failures like failing unit tests.
Enable compression for large repetitive payloads.
Skip it for tiny high-frequency messages where CPU dominates.
Split when scale and blast radius differ.
Single binary is fine for small services if ports are separated clearly.
Use bufconn for in-process integration tests.
Cover status codes, metadata, and stream EOF behavior.
Staging, local dev, or prod behind strong auth and network policy.
Never expose unauthenticated reflection on the public internet.
Implement v2 handlers that delegate to shared domain packages.
Avoid copy-pasting business rules across generated interfaces.
RPC rate, latency histograms by method, error code counters, and in-flight stream gauges.
OpenTelemetry gRPC instrumentation covers most needs.
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026