Go

What is the netpoller and how does it make network I/O look blocking yet scale?

Question 158HardGo 1.22 to 1.25

The netpoller is a runtime layer over the OS readiness APIs: epoll on Linux, kqueue on BSD/macOS, IOCP on Windows. Sockets are opened in non-blocking mode. When conn.Read gets EAGAIN, the goroutine parks on the fd's pollDesc (gopark). Neither the thread nor the P is blocked, and the P runs other goroutines.

The runtime calls netpoll in three places:

  • From findRunnable, when a P has no work.
  • From sysmon, if nobody has polled for about 10 ms.
  • From the scheduler, as a blocking wait when every P is idle.

Goroutines whose fds are ready become runnable again. Deadlines (SetReadDeadline) are integrated with runtime timers.

This gives you a simple blocking, goroutine-per-connection programming model with event-loop-level scalability. You can serve 100k idle connections with only a handful of threads.

Gotchas:

  • Regular disk files do not use the netpoller on Linux, so they block a thread.
  • Each connection still costs a goroutine stack plus buffers, often 4–10 KB or more, which matters for millions of connections.
  • DNS lookups through cgo also block threads.

More on Goroutines & the Scheduler

All 35 Goroutines & the Scheduler questions