Advanced Node.js Interview QuestionsAdvancedConcept
Node.js · Question 74
How do you handle CPU-intensive tasks in Node.js?
Direct answer
Never run long synchronous CPU work on the main thread — offload to worker_threads, child processes, or a job queue (BullMQ worker); split work into chunks with setImmediate for minor tasks; scale horizontally for sustained CPU load.
The event loop is single-threaded — a 2-second JSON.stringify loop blocks all HTTP responses, health checks, and WebSocket pings until it finishes.
| Approach | When |
|---|---|
| worker_threads | CPU-bound JS in same app — hashing, parsing |
| child_process | Isolated/untrusted code, native CLIs |
| BullMQ worker | Async jobs off API hot path — apps/worker |
| setImmediate chunking | Yield during long sync loops — last resort |
| Horizontal scale | More containers, not bigger sync blocks |
- Anti-pattern — bcrypt.sync, heavy regex on megabyte strings in route handler.
- libuv thread pool — fs/crypto DNS use threads but still limited pool (Q8).
- Measure — event loop delay (perf_hooks, clinic.js) spikes when CPU blocked.
cpu-offload.mjs
import { Worker } from "node:worker_threads";
async function hashPassword(password) {
return new Promise((resolve, reject) => {
const w = new Worker("./bcrypt-worker.mjs", { workerData: { password } });
w.on("message", resolve);
w.on("error", reject);
});
}
// Or enqueue: await emailQueue.add("send-cert", { userId });