Node.js · 16/19 5 min
Don't block the event loop
Sync fs, heavy loops and big JSON stall every request. How to spot and fix them.
Node serves every request on one thread. While your code runs, nothing else does: no other request, no timer, no I/O callback.
Common blockers
| Blocker | Fix |
|---|---|
fs.readFileSync in a handler |
await fs.promises.readFile (sync is fine at startup) |
bcrypt.hashSync, crypto.pbkdf2Sync |
the async versions run on the thread pool |
| a loop over 10 million items | paginate, stream, or move to a worker thread |
JSON.parse of a huge payload |
limit body size (express.json({ limit: "1mb" })) |
| catastrophic regex on user input | simpler patterns, cap input length |
while (Date.now() < t) {} "sleep" |
await new Promise((r) => setTimeout(r, ms)) |
Async isn't parallel
for (const id of ids) {
await fetchUser(id); // one at a time: total = sum of latencies
}
await Promise.all(ids.map(fetchUser)); // concurrent: total ≈ slowest call
For hundreds of ids, limit concurrency (batches of 10, or a small pool) so you don't flood the database.
Spotting it
- One slow endpoint makes every endpoint slow → something is blocking.
- Timers fire late (
setTimeout(fn, 100)runs after 2 s) → the loop was busy. - CPU at 100% on one core with low traffic → a hot loop.
Real CPU work
Use worker_threads (or a job queue and a separate process) for image processing, big reports and hashing in bulk. Keep the request handler short: accept, enqueue, respond 202.
Practise it now
Next in Node.js
REST API conventions tests expect