Advanced Concurrency Best Practices
Patterns for resilient concurrent APIs and services.
Search across all documentation pages
Patterns for resilient concurrent APIs and services.
These rules distill the advanced-concurrency section: bound parallelism, propagate cancellation, shut down cleanly, and prove safety with tests and profiles.
x/sync behaviorMaxOpenConns and partner API quotas.context.Context as the first parameter after the receiver. Cancel propagates through QueryContext, gRPC, and HTTP clients.r.Context() in HTTP handlers. Tie handler work to client disconnect and server shutdown.WithContext. First failure cancels siblings still doing I/O.ctx.Done() in every long loop or blocking retry. No goroutine should ignore cancel for seconds.Result structs. Do not panic from worker goroutines.atomic.Pointer. Readers load snapshots; writers publish new structs.Server.Shutdown then cancel root context.WaitGroup, errgroup Wait, or pool Shutdown in main.terminationGracePeriodSeconds.go test -race on concurrent packages in CI. Block merge on data races.pprof goroutine endpoint before major releases.Request context propagation, outbound semaphore, graceful shutdown, and -race in CI on handler packages.
Mutex around a map is usually clearer.
Channels when passing ownership between stages, not for every shared read.
No fixed number - too many is when memory, scheduling latency, or downstream errors rise without throughput gain.
Use it for parallel fetches with shared cancel.
Worker pools and simple WaitGroup joins remain valid.
Single-word metrics and flags updated at high frequency.
Multi-field invariants need mutex or transactions.
Trace startup, steady state, error path, and shutdown on paper.
Check every go has exit and every channel has one closer.
It synchronizes more aggressively but does not prevent leaks or deadlocks by itself.
Pool sizes, rate limits, shed policy, and shutdown ordering - numbers reviewers can challenge.
Acceptable when metrics needs justify dependency.
Stdlib channels plus errgroup cover most services.
After concurrency refactors and before peak season.
Automate a smoke load on every release candidate.
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 18, 2026