Node.js Event Loop Order of Execution Explained With Code
The event loop's order of execution can be confusing. Here is it explained with concrete code examples.
Node.js Event Loop Order of Execution Explained With Code
The event loop's order of execution can be confusing. Here is it explained with concrete code examples.
Microtasks Run Before Macrotasks
Promise callbacks (.then, .catch, async/await after the await) are microtasks. They run after the current operation and before the next macrotask, including before setTimeout(0) and setImmediate.
The Code Example
console.log('1'); setTimeout(() => console.log('2'), 0); Promise.resolve().then(() => console.log('3')); console.log('4');
The output is 1, 4, 3, 2. Sync code runs first (1, 4), then microtasks (3), then macrotasks (2). This is the key: microtasks run before the next macrotask.
process.nextTick vs Promises
process.nextTick callbacks run before promise callbacks, both before macrotasks. So: console.log('1'); process.nextTick(() => console.log('2')); Promise.resolve().then(() => console.log('3')); outputs 1, 2, 3. nextTick runs before promises.
Why This Matters
If you do not understand the order, you cannot predict when async code runs, which causes bugs and confusion. The order is deterministic: sync code, then microtasks (nextTick then promises), then macrotasks (timers, I/O callbacks, setImmediate).
Phases Within a Tick
Within a tick, the order is: sync code completes, then nextTick queue drains, then microtask (promise) queue drains, then the next phase of the event loop runs (timers, then poll, then check).
The Takeaway
The event loop order is: sync code, then process.nextTick, then promise microtasks, then macrotasks (timers, I/O, setImmediate). Understanding this order is essential for predicting when async code runs and debugging timing bugs.
Sync code runs first, then process.nextTick callbacks, then promise microtasks, then macrotasks (timers, I/O callbacks, setImmediate). Microtasks always run before the next macrotask, which is the key rule.
Because promises are microtasks, which run after the current operation but before the next macrotask. setTimeout is a macrotask. So in console.log('1'); setTimeout(fn); promise.then(fn); console.log('4'), the order is 1, 4, then the promise, then setTimeout.
process.nextTick callbacks. They run before promise microtasks, both before macrotasks. So console.log('1'); nextTick(fn); promise.then(fn) outputs 1, nextTick, promise. This is a Node.js-specific behavior.
Because if you do not understand the order, you cannot predict when async code runs, which causes bugs and confusion. The order is deterministic: sync, nextTick, promises, then macrotasks. Understanding it is essential for debugging timing bugs.
Microtasks are promise callbacks and process.nextTick, which run after the current operation and before the next macrotask. Macrotasks are setTimeout, setInterval, setImmediate, and I/O callbacks, which run one per event loop phase.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

