The microtask queue is a high-priority queue in the browser's event loop that runs to completion after every task — before the browser renders a new frame or picks up the next task from the regular task queue.
Understanding the difference between tasks and microtasks is what separates "it runs asynchronously" from knowing exactly when something runs.
Tasks vs Microtasks
The event loop has two distinct queues:
Task queue (macrotask queue)
setTimeout,setInterval,setImmediate- I/O callbacks, UI events (click, keydown)
MessageChannelcallbacks- The browser picks one task, runs it, then checks the microtask queue before picking the next task.
Microtask queue
Promise.then / .catch / .finallyqueueMicrotask()MutationObservercallbacksawait(which is syntactic sugar over Promise.then)- After each task ends, the browser drains the entire microtask queue before doing anything else.
The order of execution
Even though setTimeout(..., 0) is scheduled first, the Promise .then callbacks run before it — because microtasks drain before the next task is picked up.
One key rule: microtasks drain completely
The browser doesn't interleave tasks and microtasks. After a task ends, every microtask in the queue runs before anything else. If a microtask schedules another microtask, that new one also runs before the next task.
This is why Promise-based code that generates unbounded chains can lock up a page just as badly as a synchronous loop.
Why await is a microtask
Every await is a checkpoint where the function suspends and schedules its resumption as a microtask.
Why this matters for performance
Microtasks run before the browser can render a frame. A chain of .then() calls that takes 60ms to resolve will block the next paint for 60ms — even though it looks asynchronous.
The event loop article covers how tasks, microtasks, and rendering fit together in the full frame loop.
The microtask queue is the mechanism behind how Promises achieve their "runs before anything else" guarantee — and understanding it is what lets you predict, and control, the exact order your async code executes.
