Phases refresher

  • timers → pending → idle/prepare → poll → check → close callbacks.
  • Microtasks (Promises/queueMicrotask) run after each phase; process.nextTick runs before microtasks.

Pitfalls

  • Long JS on main thread blocks poll → delays I/O; move CPU work to worker threads.
  • nextTick storms can starve I/O; prefer setImmediate when deferring.
  • Unhandled rejections crash (from Node 15+ default); handle globally in prod.

Debugging

  • NODE_DEBUG=async_hooks or --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.