How many goroutines can a Go program run? How do you bound them?
The language sets no limit. In practice the limit is memory: at least about 2 KB of stack each, plus whatever each goroutine references. One million idle goroutines use roughly 2.5–4 GB. Hundreds of thousands are routine. The real cost of too many is not creating them. It is the memory, GC scan work (every stack is a root), scheduler overhead, and pressure on downstream resources such as file descriptors, database connections and rate limits.
Bound the work with a worker pool, a semaphore channel, errgroup.SetLimit or golang.org/x/sync/semaphore:
func processAll(ctx context.Context, items []Item) error {
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(runtime.GOMAXPROCS(0) * 4)
for _, it := range items {
g.Go(func() error { return process(ctx, it) })
}
return g.Wait()
}
The limit on OS threads is separate. It defaults to 10,000 (debug.SetMaxThreads) and is reached through blocking syscalls or cgo, not through ordinary goroutines.
What the interviewer wants to hear: "goroutines are cheap" does not mean "spawn one per item without limit". You back-pressure at the boundary, choose the pool size based on whether work is CPU- or I/O-bound, and measure.
More on Goroutines & the Scheduler
- Q162What is a goroutine leak? Give common causes.
- Q163How do you detect and debug goroutine leaks in production and tests?
- Q165Why doesn't Go expose goroutine IDs, and how do you "kill" a goroutine?
- Q166What happens when main returns while other goroutines are still running? What does this print?
- Q167What happens if a goroutine panics? Can the parent recover it?
- Q168What does this print? (Closure capture and the Go 1.22 loop variable change)