Lesson 26 · Senior Go backend engineering

errgroup & bounded concurrency

The senior answer when work can fail, cancel siblings, or arrive in huge batches.

Your win: know when errgroup is better than WaitGroup, explain fail-fast fan-out in plain English, and describe bounded concurrency the way a senior backend engineer would — as overload control, not just as a syntax trick.

In plain English If several goroutines together represent one operation, they should usually share one fate: if one fails badly enough, the whole operation should stop cleanly. That is the niche errgroup fills.

Why this matters beyond syntax

The difference between junior and senior concurrency answers is often not “knows more packages.” It is “can explain lifecycle.” Who starts the work? Who cancels it? Who owns the first failure? What stops the input size from turning into unbounded goroutines?

The mental model WaitGroup answers “have these goroutines finished yet?” errgroup answers “how does this whole concurrent operation succeed, fail, and stop?”

The shape of an errgroup operation

g, ctx := errgroup.WithContext(ctx)
g.SetLimit(8)
for _, job := range jobs {
    job := job
    g.Go(func() error {
        return process(ctx, job)
    })
}
if err := g.Wait(); err != nil {
    return err
}
Backend use case This repo already has worker pools, fan-out, and background work. The senior question is not “can I launch a goroutine?” It is “should this be independent background work, a bounded worker pool, or one errgroup-shaped operation that fails fast under one parent context?”
Common mistake Using a raw WaitGroup for work that can fail. If one child errors and the others keep chewing CPU, memory, or downstream capacity, you do not have structured concurrency — you have cleanup debt.
Read this next

Pipelines, cancellation, and x/sync

The Go blog gives the cancellation story; errgroup is the practical helper that makes that story ergonomic in production code.

go.dev/blog/pipelines
pkg.go.dev/golang.org/x/sync/errgroup

Check yourself (from memory)

Q1. The senior reason to prefer errgroup over WaitGroup is…

The main upgrade is semantics — failure and cancellation — not shorter syntax.

Q2. Bounded concurrency protects a service from…

Limits are a load-shaping tool. They keep big inputs from turning into runaway runtime cost.
Give the one-sentence definition of bounded concurrency.
recall, then click to reveal
A design that caps how much work may run at once so large inputs or spikes do not turn into unbounded goroutine, memory, and latency growth.
Want a decision table comparing WaitGroup, worker pools, semaphores, and errgroup? Ask me.

Sources. Pipelines and cancellation; errgroup docs.