← Lessons

quiz vs the machine

Gold1410

Concurrency

Thread Pools for IO

Offloading blocking calls to a bounded set of workers so the event loop stays responsive.

5 min read · core · beat Gold to climb

Why an event loop needs help

An event loop is fast only while every handler returns quickly. The moment a handler makes a blocking call, such as a DNS lookup or a synchronous file read on a platform without async file IO, the whole loop freezes. A thread pool solves this by giving the loop somewhere to hand blocking work.

How the offload works

The loop submits the blocking task to a pool of worker threads and immediately returns to processing events. A worker picks up the task, performs the blocking call, and when finished posts the result back to the loop, which then runs the continuation. Node uses exactly this with its libuv worker pool for file system and DNS work.

  • The pool is bounded so blocking work cannot spawn unlimited threads
  • Queued tasks wait when all workers are busy, applying natural backpressure
  • The event loop thread never blocks, so other connections stay responsive

Sizing the pool

A pool serving blocking IO can be larger than the core count, since workers spend most of their time waiting rather than computing. Too small and tasks queue up, adding latency. Too large and you waste memory and risk thrashing.

Key idea

A bounded thread pool absorbs blocking calls off the event loop, keeping the loop responsive while workers do the slow synchronous work.

Check yourself

Answer to earn rating on the learn ladder.

1. Why offload a blocking call to a thread pool instead of running it on the event loop?

2. Why is a bounded pool important?