Server

Event loop

Event loop is the single-threaded cycle that Node.js uses to pick up finished I/O and run its callbacks. If your code holds the loop, nothing else gets a turn.

How it is measured

The key measure is event loop delay: how late a scheduled timer fires compared with when it was due. Node exposes it through `perf_hooks.monitorEventLoopDelay`, and you report p50, p99 and max in milliseconds.

Healthy services show delay of a few milliseconds. Sustained p99 above 100 ms means something is running synchronously for too long, such as JSON parsing, a regex or a large loop.

Worked example

An Express API serves 200 requests per second. A new endpoint parses a 14 MB JSON upload with `JSON.parse`, blocking the loop for 180 ms each time. While one upload parses, every other request, even a 2 ms health check, waits.

Event loop p99 climbs from 4 ms to 190 ms, and the load balancer starts failing health checks. Streaming the parse in a worker thread brings the delay back below 10 ms.

How it differs

The event loop is the scheduler that runs your callbacks on one thread. A worker thread is a separate thread that can run heavy JavaScript beside it. The loop excludes parallel CPU work, and worker threads exclude the cheap callback switching the loop provides. The first is why Node handles many sockets, the second is how it escapes CPU limits.

Common errors

Doing synchronous file reads or crypto inside a request handler. Assuming async/await makes CPU work non-blocking. Running a regex on untrusted input and inviting catastrophic backtracking. Measuring only request time and never loop delay. Using one long loop to process a large array.

In practice

Add `monitorEventLoopDelay` to your metrics and alert when p99 stays above 100 ms. Find the longest synchronous task with a CPU profile, then break it up, stream it, or push it to a worker.

See also

Worker thread, I/O-bound

Sources

Count this on a real site.

Watch my website