What happens when you use an old tool that never gives the seat back? You told everyone you would call them when their turn came — and then sat at the counter waiting for your own answer.
See this first in FoundationsWhen does an event loop win, and when does it lose?Not every library is non-blocking: old database drivers, synchronous file IO, some HTTP clients simply stop until the result arrives. What happens when you call one on the event loop? Flip the toggle and see.
There is one thread. Call a blocking function and it drops to Waiting exactly as in chapter 7, leaving the CPU. No matter how many events pile up, nobody is there to take them off the queue.
Turn the toggle on and completion collapses. A server that was juggling dozens of requests now handles one at a time, because throughput is limited to the thread count — which is one.
One blocking database call in a reactive stack, or one synchronous file read in Node, is enough. That is why these frameworks insist that every IO in the stack be non-blocking, and why unavoidable blocking work must be isolated onto a separate thread pool.
A blocking call is syntactically fine. It compiles, tests pass, and under light load it even behaves. The failure only appears once concurrency rises. Because no type system stops you, one synchronous database driver in a reactive stack, or one synchronous HTTP client inside a coroutine, slips in naturally.
Draw this distinction carefully: a blocked thread uses no CPU. So utilisation looks low while the server serves nobody. Worse, if that thread is holding a database connection or a lock, the resource is held too. Many real outages are exactly this chain — a slow external call ties up a thread, the thread ties up a connection, and once the pool is dry every request to that service dies.
If blocking cannot be removed, two things are mandatory. One is isolation: confine blocking work to a dedicated pool so that exhausting it leaves the rest of the service alive. The other is timeouts: a blocking call without one holds resources for as long as the other side stays silent. That is the most common path by which an upstream outage silently becomes yours.
Try it in the simulator
Terms in this chapter
One blocking line on the loop = the whole server stops.
The remaining problem
That is the methods and their traps. But why were they born in exactly this order? →