What does it mean to "block the event loop," and how do you avoid it?
3 minintermediatenodejsblockingevent-loopperformancecpu
Quick Answer
Blocking means running long synchronous (usually CPU-bound) code on the main thread so the event loop can't process other callbacks — every client stalls. Avoid it by chunking work, using async/streaming APIs, and offloading heavy computation to worker threads or a separate service.
Detailed Answer
Answer: Because your JavaScript runs on one thread, any long-running synchronous operation prevents the event loop from handling other events. Requests queue up and latency spikes for all clients.
Common culprits:
- Tight CPU loops (image processing, encryption, big data transforms).
- Synchronous FS calls (
fs.readFileSync) on hot paths. JSON.parse/JSON.stringifyon very large payloads.- Complex synchronous regexes (ReDoS).
crypto.pbkdf2Sync/bcryptsync variants.
// ❌ Blocks the loop — no other request is served during this
app.get('/hash', (req, res) => {
const result = expensiveSyncHash(req.query.data);
res.send(result);
});
Ways to avoid blocking:
- Use async APIs —
fs.promises.readFile, async crypto (crypto.pbkdf2), etc. - Offload CPU work to
worker_threads(or a job queue / separate microservice):
const { Worker } = require('worker_threads');
app.get('/hash', (req, res) => {
const worker = new Worker('./hash-worker.js', { workerData: req.query.data });
worker.once('message', result => res.send(result));
});
- Chunk long loops — break work across ticks with
setImmediateso I/O gets turns. - Stream large data instead of buffering it all in memory.
Diagnosing: watch event-loop lag (e.g., perf_hooks.monitorEventLoopDelay), and profile with --prof or clinic.js.