Event Loopcritical

Microtask Queue

The microtask queue holds Promise .then()/.catch()/.finally() callbacks and queueMicrotask() callbacks. Microtasks run before the event loop moves to the next phase.

Memory anchor

Microtasks are like post-it notes stuck to your current task. You MUST handle every post-it before moving to the next agenda item (phase). nextTick post-its are neon pink (highest priority); Promise post-its are yellow. A pile of 10,000 post-its = nothing else gets done.

Expected depth

Node.js maintains two microtask queues: the nextTick queue (highest priority) and the Promise microtask queue. After each synchronous block and between event loop phases, Node drains nextTick completely first, then drains Promise microtasks completely. This ordering changed in Node.js 11—prior to that, microtasks only ran between full loop iterations.

Deep — senior internals

queueMicrotask() enqueues directly to the Promise microtask queue (same level as Promise.resolve().then()). async/await is syntactic sugar over Promises, so await suspension points enqueue microtasks. A common gotcha: in an async function, code after every await is a microtask callback. If you await inside a loop over thousands of items, you're creating thousands of microtask continuations that drain before any I/O can fire—effectively blocking I/O for the duration. The fix is to periodically yield with setImmediate or await a small timeout.

🎤Interview-ready answer

Microtasks (Promise callbacks, queueMicrotask) run after each synchronous block and between every event loop phase. process.nextTick has even higher priority and drains before Promise microtasks. Since Node.js 11, microtasks drain between phases, not just between full loop iterations—this changed observable behavior for code mixing setImmediate and resolved promises.

Common trap

Awaiting inside a for-of loop over a large array doesn't yield I/O control. Each await on an already-resolved promise enqueues a microtask that runs before the next event loop phase—your loop monopolizes the main thread even though it's written with await.

Related concepts