DevAcademy
LearnNode.jsThe Event Loop in Node.js
IntermediateNode.js

The Event Loop in Node.js

A closer look at how Node.js schedules callbacks, and its distinct phases.

Reading Time

16 min

Lesson

Lesson 13 of 34

Phases of the Event Loop

Node.js's event loop runs through a fixed set of phases repeatedly, each dedicated to a specific kind of callback. Unlike the browser's simpler task/microtask model, Node.js has several distinct phases for different sources of async work.

Main Phases (Simplified)

PhaseHandles
TimersCallbacks scheduled by setTimeout and setInterval
Pending CallbacksSome system-level callbacks deferred from the previous cycle
PollFetching new I/O events; executes I/O callbacks (like a completed file read)
ChecksetImmediate() callbacks
Close CallbacksCleanup, like socket "close" events

setTimeout vs setImmediate

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Microtasks Run Between Every Phase

Promise callbacks (via .then()) and process.nextTick() are microtasks — they run to completion after the currently executing operation finishes, before the event loop proceeds to the next phase. process.nextTick() has even higher priority than resolved promises.

Ordering Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Why This Matters in Practice

You rarely need to reason about exact phase ordering day to day — but understanding that promises resolve before timers, and that nextTick has the highest priority, explains a lot of subtle async bugs when they do come up.

Best Practice

Avoid process.nextTick() recursion (calling nextTick from within a nextTick callback repeatedly) — because it runs before the event loop can proceed to I/O, an unbounded recursive chain can starve I/O entirely.

Interview Questions

Quick Quiz

1. What is process.nextTick() relative to resolved Promise callbacks?

2. In the ordering example, why does synchronous code ("1" and "5") run before everything else?

3. What can happen if process.nextTick() is called recursively without bound?