How Go's net/http server handles millions of concurrent connections. Goroutine-per-request, HTTP/2 stream multiplexing, connection pooling, and the real limits of throughput.
Go's net/http.Server spawns a new goroutine for every accepted TCP connection. Each goroutine costs ~2–8 KB of stack (grows as needed). This is how Go handles 100K+ concurrent connections on a single machine.
HTTP/1.1 sends one request per TCP connection at a time (head-of-line blocking). HTTP/2 multiplexes many streams over a single TCP connection — parallel requests, no blocking.
Go's http.Transport maintains a pool of idle TCP connections per host. It reuses connections instead of creating new ones for every request — critical for high-throughput HTTP clients.
A Go HTTP server can handle 100K–1M+ requests per second on modern hardware. The bottleneck is almost never the HTTP layer — it's your handler code, database calls, or network I/O.
Without timeouts, slow clients or backends cause goroutine leaks — each stuck goroutine holds memory and a connection forever. Go's net/http has ZERO default timeouts. You must set them.
Go 1.22 introduced enhanced ServeMux with method matching and path parameters. Before that, the default mux was embarrassingly simple — just longest-prefix matching on the path.