Goroutines are cheap — 4KB stacks, fast scheduling. So 'just spawn one per task' is reasonable up to ~100K concurrent. Past that, even the cheap things have costs, and patterns shift.
Worker pools over unbounded goroutines
Spawning one goroutine per incoming request is fine until incoming rate spikes. Use bounded worker pools to cap concurrency; queue overflow with explicit backpressure (drop, reject, or block).
Channel patterns under load
Buffered channels: smooth out producer/consumer mismatch. Select with default: non-blocking sends (good for shedding load). Closing channels signals 'no more work' to N consumers cleanly.
Memory model gotchas
Goroutine N stack starts at 8KB; grows. 100K goroutines = ~1-10GB stack memory under normal use. Profile pprof goroutine count and stack sizes. Long-lived goroutines that don't exit are memory leaks.