By Rahul — Google Frontend Engineer
Why This Matters
If you do not understand microtasks and macrotasks, you cannot predict when your code runs. This leads to race conditions, UI freezes, and bugs that only appear under load.
The Event Loop — Simplified
The browser event loop follows this cycle:
- Pick ONE macrotask from the queue (or wait for one)
- Execute it completely
- Execute ALL microtasks in the microtask queue (including any new ones added during this step)
- Render (if needed — approximately every 16ms)
- Go to step 1
What Goes Where?
Macrotasks
setTimeout/setIntervalsetImmediate(Node.js only)- I/O operations
- UI rendering events
MessageChannelrequestAnimationFrame(technically before render, but after microtasks)
Microtasks
Promise.then/catch/finallyqueueMicrotask()MutationObserverasync/await(the code after await)
The Classic Interview Question
The Dangerous Part: Microtask Queue Draining
Compare with setTimeout:
Real Production Example
async/await and Microtasks
Best Practices
- Use
queueMicrotask()when you need something to run after current code but before rendering - Use
setTimeout(fn, 0)when you need to yield to the browser for rendering - Never create infinite microtask loops
- Use
requestAnimationFramefor visual updates
Summary
Microtasks run after the current task but before rendering. Macrotasks run one at a time with rendering between them. Understanding this determines whether your UI stays responsive.