setTimeout vs setImmediate vs nextTick
By FrontendPro Editorial Team Updated 9/26/2026
Answer
All three defer work, but they run at different points in Node's event loop. Two of them are Node-only — browsers have setTimeout and queueMicrotask.
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
Promise.resolve().then(() => console.log("promise"));
console.log("sync");
// sync, nextTick, promise, timeout/immediate (order of the last two varies)
The ordering rule
process.nextTick runs first, before the loop continues at all, and before promise callbacks. Promise.then runs next, in the microtask queue. Only then does the loop proceed to its phases.
setTimeout(fn, 0) runs in the timers phase and setImmediate in the check phase. From the main module their relative order is not deterministic — it depends on how long process startup took. Inside an I/O callback, however, setImmediate always wins, because the check phase comes right after I/O.
Why nextTick needs care
It is not part of the loop; its queue is drained completely after the current operation and before anything else. A recursive nextTick starves the loop entirely — timers never fire and I/O never completes:
function loop() { process.nextTick(loop); }
loop(); // the process hangs
setImmediate recursion does not do this, because each iteration yields to the loop.
Which to use
setImmediateto run after the current phase, yielding to I/O — the safe "do this next tick" in Node.setTimeoutwhen you want an actual delay. Note0is clamped to at least 1 ms, and nested timeouts are clamped to 4 ms.process.nextTickrarely, and only to run something before any I/O — for example emitting an error after the constructor returns.
In the browser, use queueMicrotask for the nextTick role and setTimeout for the rest.
