Event Loophigh

setImmediate vs setTimeout

setImmediate schedules a callback after the poll phase (check phase). setTimeout(fn, 0) schedules a callback after a minimum delay (≥1ms) in the timers phase. Both defer execution, but to different event loop phases.

Memory anchor

setImmediate = 'I'll do it right after this meeting (poll phase).' setTimeout(0) = 'I'll do it first thing tomorrow morning (next timers phase).' Inside an I/O callback, you're already in the meeting, so setImmediate always wins the race home.

Expected depth

When called from the main module (outside I/O callbacks), their execution order is non-deterministic because it depends on whether the timer's 1ms minimum has elapsed by the time the timers phase runs. Inside an I/O callback, setImmediate always executes before setTimeout(fn, 0) because the event loop has already passed the timers phase for that iteration and will reach check before looping back to timers.

Deep — senior internals

The 1ms minimum timer resolution is a libuv implementation detail inherited from OS timer APIs. On Linux, the minimum timer resolution is typically 1ms; on Windows it can be up to 15ms. Under load, the timers phase may see a setTimeout(fn, 0) as not yet expired even though nominally 0ms have passed. For guaranteed post-I/O, post-poll ordering, setImmediate is the correct tool. setImmediate also has a meaningful performance advantage in high-throughput scenarios because it doesn't involve timer heap management in libuv.

🎤Interview-ready answer

setImmediate fires in the check phase (after poll); setTimeout(fn, 0) fires in the timers phase (start of loop). From the main module their order is non-deterministic. Inside an I/O callback, setImmediate always fires first. When you need to defer work until after I/O callbacks in the current iteration, setImmediate is the correct choice.

Common trap

Assuming setTimeout(fn, 0) fires before setImmediate anywhere is wrong. The order is only guaranteed inside I/O callbacks. Benchmarks and tests that rely on their relative ordering from the main script will produce flaky results across machines and Node versions.