OS + NetworkingIntermediate

Blocking servers vs event-driven servers

“Compare a thread-per-connection server with an event-driven one. What is actually blocking, in the kernel, when a thread "blocks"? When is each design the right one?”

What this tests

  • Understanding what a blocked thread is (sleeping in the kernel on a wait queue)
  • The difference between concurrency (many waits) and parallelism (many cores)
  • The one rule of event loops: never block the loop
  • Judgement about when threads are the better tool

Answers by level

Read the beginner answer first and notice what is missing.

When a thread calls recv() on a socket with an empty receive buffer, the kernel puts it on the socket’s wait queue and schedules something else; the thread is not consuming CPU, it is simply not runnable. Its cost is memory (stack, kernel task) and the context switch when it wakes. A thread-per-connection server is easy to write because each handler reads like straight-line code.

An event-driven server keeps one thread (per core) that never blocks on I/O: it registers all sockets with epoll, waits once for any readiness, and runs a short handler per ready socket. The waiting is done by the kernel for all sockets at once, so idle connections cost nothing but memory.

The trade: the event loop must never block — a synchronous file read, a DNS lookup, a CPU-heavy JSON parse, or a sync database driver stalls every connection. Those go to a worker pool. Threads are the right choice when handlers are CPU-heavy, when the language lacks good async I/O, or when connection counts are modest and simplicity wins.

Green flags · Red flags

Strong green flag · Identifies hidden blocking (sync driver, libuv pool, GC pause) as the way event-driven servers actually fail in production.
Green flags
  • Describes a blocked thread as sleeping in the kernel, not spinning
  • States the "never block the loop" rule with examples
  • Knows the hybrid: loops plus a worker pool
  • Can name a case where threads are better
Red flags
  • "Async is faster" with no mechanism
  • Thinks blocked threads burn CPU
  • Believes event-driven means parallel
  • Cannot explain what epoll returns

Follow-up questions

F1
A Node service’s p99 jumps to 2 s under load while CPU is at 40%. First hypothesis?
F2
Why does Python asyncio not make CPU-bound code faster?

Scenario

You are told to "make the API async" because it is slow. The handlers each do a 300 ms CPU-bound image resize. Will async help? What will?

Learn this topic