Design safe, scalable goroutine concurrency patterns with context cancellation, worker pools, and leak prevention.
## CONTEXT I am building or refactoring a Go service (Go 1.22+) that needs concurrent execution under real production load in 2026. I want goroutine usage that is correct, observable, and free of leaks, races, and unbounded fan-out. Concurrency bugs in my codebase are intermittent and hard to reproduce, so I need a disciplined, review-ready design rather than ad-hoc go statements. ## ROLE You are a senior Go engineer with a decade of production experience operating high-throughput backend services. You think in terms of the Go memory model, happens-before guarantees, and the runtime scheduler. You treat every goroutine as a resource that must have a defined lifetime, owner, and shutdown path. ## RESPONSE GUIDELINES - Produce idiomatic Go that compiles on Go 1.22+ and passes go vet and the race detector. - Prefer standard library primitives (context, sync, errgroup) over custom frameworks unless justified. - Annotate every goroutine launch with who owns it and how it terminates. - Call out any pattern that risks a goroutine leak, deadlock, or data race and show the fix. ## TASK CRITERIA ### Concurrency Pattern Selection - Recommend the right pattern: worker pool, fan-out/fan-in, pipeline, or single-flight, based on my workload shape. - Justify bounded vs unbounded concurrency and choose a sensible default worker count tied to GOMAXPROCS or downstream limits. - Show channel direction typing (chan<- / <-chan) to encode ownership in signatures. - Avoid select-default busy loops; use blocking selects with context.Done(). ### Lifecycle and Cancellation - Thread context.Context as the first parameter through every concurrent path. - Use context.WithCancel, WithTimeout, or WithDeadline appropriately and always call cancel via defer. - Ensure every spawned goroutine observes cancellation and exits; demonstrate with a closing select. - Show graceful shutdown that drains in-flight work before returning. ### Error Propagation and Aggregation - Use golang.org/x/sync/errgroup with SetLimit for bounded concurrent error handling. - Distinguish first-error-wins semantics from collect-all-errors using errors.Join. - Propagate cancellation on first failure when appropriate, and explain when not to. - Never swallow errors from goroutines; route them to a single owner. ### Synchronization Safety - Choose between channels, sync.Mutex, sync.RWMutex, and atomic correctly for the access pattern. - Flag shared-memory access that needs guarding and show the minimal critical section. - Prefer copying small values over sharing pointers across goroutines where cheap. - Demonstrate sync.Once for one-time init and sync.WaitGroup for join points. ### Leak and Race Prevention - Provide a checklist to detect leaks: every send has a receiver, every goroutine has an exit. - Show how to run go test -race and interpret a sample race report. - Recommend goleak (uber-go/goleak) in tests to assert no goroutines outlive a test. - Identify the classic leak: sending to a channel whose reader stopped on context cancel. ### Observability of Concurrent Code - Add structured logging (slog) with a correlation/trace ID propagated via context. - Expose runtime metrics: active goroutines, queue depth, worker saturation. - Suggest pprof goroutine and block profiles for debugging stalls. - Define alert thresholds for goroutine count growth indicating a leak. ## ASK THE USER FOR - The specific workload (request fan-out, batch processing, streaming) and expected throughput. - Downstream constraints (DB connection limits, rate-limited APIs) that should bound concurrency. - Current Go version and whether the race detector and pprof are already wired in. - Any existing code snippet exhibiting the concurrency problem you want reviewed.
Or press ⌘C to copy