Back to homepage

image

If you’ve ever wondered why your callback runs after your , or what makes so special,here’s my take on how the event loop really works, minus the textbook jargon.


🧠 Node.js Event Loop: The Real-World Version

Node.js runs everything on a single thread, but it’s surprisingly good at juggling lots of things at once. The secret? It splits up work into macrotasks and microtasks—think of them as two different to-do lists.

Each time Node.js goes through its event loop (a “tick”), it:

  1. Runs one macrotask.
  2. Then, empties the microtask queue (runs all microtasks).
  3. Then, moves on to the next macrotask.

🟩 Macrotasks: The Big Stuff

Macrotasks are the “main events”—timers, I/O, and things you schedule with:

  • setTimeout()
  • setInterval()
  • setImmediate() (Node.js only)
  • I/O callbacks (like reading files or handling HTTP requests)

Example:

setTimeout(() => {
console.log('Macrotask: Timeout');
}, 0);

Macrotasks always wait for microtasks to finish before they run.


🟦 Microtasks: The Quick Fixes

Microtasks are the “urgent” tasks—stuff that should happen right after the current code finishes, but before any new macrotask starts.

You get microtasks from:

  • Promise.then() / catch() / finally()
  • queueMicrotask()
  • process.nextTick() (special Node.js case—see below!)

Example:

Promise.resolve().then(() => {
console.log('Microtask: Promise.then');
});

🔁 : Node’s VIP Pass

is Node’s way of saying, “Run this callback before anything else, even before other microtasks.”

Example:

process.nextTick(() => {
console.log('process.nextTick');
});

⚠️ Heads up: If you keep scheduling inside itself, you can starve the event loop—nothing else will get a turn.


🕘 Who Runs First? (Execution Order)

Let’s see it in action:

console.log('Start');
setTimeout(() => {
console.log('Macrotask: setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('Microtask: Promise.then');
});
process.nextTick(() => {
console.log('Microtask: process.nextTick');
});
console.log('End');

What you’ll see:

Start
End
Microtask: process.nextTick
Microtask: Promise.then
Macrotask: setTimeout

🧭 Quick Reference Table

Task TypeHow You Get OneWhen It Runs
MacrotasksetTimeout, setInterval, I/OAfter all microtasks
MicrotaskPromise.then, queueMicrotaskBefore macrotasks, after current code
process.nextTickprocess.nextTick()Before all other microtasks