All Posts
Node.js

Understanding the Node.js Event Loop (For Real This Time)

August 16, 2025

Most explanations of the Node.js event loop stay abstract. Here's a version grounded in an actual code example, because the phase ordering only really sinks in once you can predict the output.

The Phases, In Order

  1. Timers — runs callbacks scheduled by setTimeout/setInterval
  2. Pending callbacks — certain system-level callbacks
  3. Poll — retrieves new I/O events, executes I/O callbacks
  4. Check — runs setImmediate callbacks
  5. Close callbacks — e.g. socket.on('close')

Microtasks Jump the Queue

Promises (.then) and process.nextTick aren't part of the phase cycle above — they run in a microtask queue that's fully drained after every single callback, before the event loop moves to the next phase.

A Concrete Example

console.log('start');

setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));

Promise.resolve().then(() => console.log('promise'));
process.nextTick(() => console.log('nextTick'));

console.log('end');

// Output:
// start
// end
// nextTick
// promise
// timeout (or immediate — order can vary here)
// immediate (or timeout)

Why This Matters in Practice

A synchronous CPU-heavy loop blocks the entire event loop — no timers, no I/O callbacks, nothing runs until it finishes, even in a language people call "non-blocking." Understanding the phases is really about understanding what Node.js is doing while your code is idle, which is most of the time in a typical I/O-bound server.