← Concepts

阅读中文版本

Goroutine and Task Leaks

A task leak is a coroutine or goroutine that never finishes because it waits forever on a channel or condition, slowly exhausting resources.

concurrency

Definition

A goroutine leak is a permanently blocked lightweight task that holds memory and possibly other resources because nothing will ever unblock it.

Context and scope

It appears in servers that spawn tasks per request or subscription when cancellation paths are missing.

Common misconceptions

  • leaked tasks are harmless because they are cheap
  • the garbage collector reclaims blocked tasks

Anti-patterns

  • starting a task that sends to an unbuffered channel nobody reads
  • missing a context cancellation on a long-lived subscription

Related concepts

Related examples

Authoritative source

https://go.dev/doc/go1.22

Definition

A goroutine leak is a permanently blocked lightweight task that holds memory and possibly other resources because nothing will ever unblock it.

It appears in servers that spawn tasks per request or subscription when cancellation paths are missing. Compared to simpler alternatives, this concept fits best when the trade-off it represents is the one the system actually cares about.

When to use it

A common use case is applying it at the boundary where the cost of getting it wrong is highest, and the scenario usually involves a concrete guarantee the system must uphold. Unlike an ad hoc approach, it makes that guarantee explicit, reviewable, and testable.

How it works

A task blocked on a channel send or receive stays reachable and keeps its stack, so a leak grows unboundedly under sustained traffic and eventually exhausts memory.

Every task that waits must have a path to exit, typically by selecting on a cancellation signal alongside the data channel.

Trade-offs and alternatives

Leak detectors and runtime task counts reveal the pattern, because the count climbs monotonically and never falls back after load subsides. The main drawback is the extra complexity it introduces, so the benefit should clearly outweigh that cost before a team adopts it.

Common misconceptions

A persistent misconception is that leaked tasks are harmless because they are cheap. Another is that the garbage collector reclaims blocked tasks. For example, an engineer who assumes otherwise may design around a guarantee that does not actually exist, which only becomes obvious under load or failure.

Anti-patterns to avoid

Two recurring anti-patterns are to starting a task that sends to an unbuffered channel nobody reads and to missing a context cancellation on a long-lived subscription. Both tend to surface as hard-to-debug production issues rather than obvious test failures. Related concepts include I/O Multiplexing with epoll and kqueue, Atomic Operations, Seqlocks.