Node runs your synchronous code first, then repeatedly processes queued work in phases: timers (`setTimeout`/`setInterval`), pending I/O callbacks, `setImmediate`, and close callbacks. Between phases it drains microtasks — resolved Promises (`.then`) and `process.nextTick` — before moving on.
This ordering explains a classic surprise: a `Promise.resolve().then(...)` scheduled after a `setTimeout(fn, 0)` still runs first, because microtasks are drained before the next macrotask phase.
js
console.log("1");
setTimeout(() => console.log("2 - timer"), 0);
Promise.resolve().then(() => console.log("3 - microtask"));
console.log("4");
// prints: 1, 4, 3 - microtask, 2 - timerUnderstanding the loop matters once you write anything that mixes timers, network callbacks and promises — which is essentially every real Node service.