Yeda AI Tips · #113

Español

Never Launch a Goroutine Without an Owner

The invisible leak in AI-generated Go services is a goroutine launched with no owner. AI assistants love the go keyword — it's one word, it compiles, and the demo works. But goroutines are not garbage collected. The Go team's own pipelines article is blunt: "goroutines consume memory and runtime resources, and heap references in goroutine stacks keep data from being garbage collected. Goroutines are not garbage collected; they must exit on their own." A goroutine with no cancellation signal and no bounded worker model never exits. It leaks quietly — a few KB of stack each, plus everything its stack references — until your service falls over.

Why AI-generated Go leaks

Generated code optimizes for "compiles and passes the happy path." The classic pattern looks harmless:

go func() {
    for msg := range ch {
        process(msg)
    }
}()

Who closes ch? Who waits for this goroutine on shutdown? What stops it if the caller's request is cancelled? If you can't answer all three by reading the launch site, you have a leak. Under load, blocked senders pile up behind a receiver that stopped reading, and each one pins its message in memory forever.

The ownership contract

Every goroutine needs an owner whose lifetime is visible where it's launched. Three mechanisms cover it:

ConcernMechanismRule of thumb
How does it stop?context.Context cancellationPass ctx in; select on ctx.Done() in every blocking loop
Who closes the channel?Sender-side closeOnly the goroutine that sends on a channel closes it — never the receiver
Who waits for it?sync.WaitGroupwg.Add(1) before go, defer wg.Done() inside, wg.Wait() on shutdown

Put together, an owned goroutine reads like this:

wg.Add(1)
go func() {
    defer wg.Done()
    for {
        select {
        case <-ctx.Done():
            return
        case msg, ok := <-ch:
            if !ok {
                return
            }
            process(msg)
        }
    }
}()

Cancellation, channel ownership, and cleanup are all obvious at the launch site — which is exactly what makes generated code reviewable.

Red flags to hunt in a review

Power-user moves

Resources

Building an AI feature? Yeda AI designs, audits, and ships production LLM systems.

Talk to us · Read the blog