Skip to content

The Event Loop

The single-threaded scheduler at the heart of every async runtime — it repeatedly asks the OS "what's ready," runs the corresponding callbacks/ coroutines, and loops. Understanding its actual loop structure explains both async's power and its sharpest footgun (a slow callback blocks everything).

flowchart LR Junior["Junior: the loop's basic structure - poll, dispatch, repeat"] --> Middle["Middle: epoll/kqueue/io_uring as the readiness mechanism"] Middle --> Senior["Senior: why one slow callback blocks the entire loop"] Senior --> Professional["Professional: io_uring vs. epoll - true async I/O vs. readiness-based"]
flowchart LR Loop["Event loop, forever:"] --> Poll["1. Poll OS: what's\nready?"] Poll --> Dispatch["2. Run callbacks for\nready events"] Dispatch --> Loop

Choose a level

Level Guide You are done when
Junior The loop's basic structure You can describe the poll-dispatch-repeat cycle in your own words.
Middle epoll/kqueue/io_uring You can explain what a readiness-based API actually tells the event loop.
Senior Why one slow callback blocks everything You can trace why a synchronous, slow operation inside a callback stalls the entire loop.
Professional io_uring vs. epoll You can explain the architectural difference between readiness-based and true-async I/O models.

Practice rule

For any callback/handler registered with an event loop, ask: "does this ever call a blocking, synchronous operation (file I/O, a CPU-heavy computation, a synchronous library call)?" If yes, it will stall every other task on that loop for its duration — this is the single most common async programming bug.