Phases refresher
- timers → pending → idle/prepare → poll → check → close callbacks.
- Microtasks (Promises/
queueMicrotask) run after each phase;process.nextTickruns before microtasks.
Pitfalls
- Long JS on main thread blocks poll → delays I/O; move CPU work to worker threads.
nextTickstorms can starve I/O; prefersetImmediatewhen deferring.- Unhandled rejections crash (from Node 15+ default); handle globally in prod.
Debugging
NODE_DEBUG=async_hooksor--trace-events-enabled --trace-event-categories node.async_hooks.- Measure event loop lag:
perf_hooks.monitorEventLoopDelay(). - Profile CPU with
node --inspect+ Chrome DevTools; use flamegraphs for hotspots.
Practices
- Limit synchronous JSON/crypto/zlib; offload to worker threads or native modules.
- Keep microtask chains short; avoid deep promise recursion.
- Use AbortController for cancellable I/O; always clear timers.
Checklist
- Monitor event loop lag & heap usage.
- Worker pool sized for CPU tasks; main loop kept light.
- Errors and rejections centrally handled; graceful shutdown in place.