Worker Threads
Run CPU-bound work in parallel without freezing the event loop
worker_threads lets you move that computation onto a separate thread with its own event loop and V8 isolate, so the main thread stays responsive.
- explain why CPU-bound work blocks the event loop while I/O does not;
- spawn a
Workerand exchange data withpostMessage/workerData; - use transferable objects to move buffers with zero copy;
- share memory across threads with
SharedArrayBufferandAtomics; - choose correctly between worker threads, cluster, and child_process.
1. Why the event loop needs help
You already know the event loop keeps Node responsive by never blocking on I/O: a database query or a file read is handed to the OS (or a libuv thread) and your callback runs later. The catch is that your JavaScript itself still runs on one thread. If a function spends 3 seconds hashing a password with a large cost factor, or resizing a 40-megapixel image, or parsing a huge CSV, nothing else on that thread can run for those 3 seconds.
// This blocks the whole process for as long as it runs
function fib(n) { return n < 2 ? n : fib(n - 1) + fib(n - 2); }
app.get('/slow', (req, res) => res.json({ result: fib(45) })); // ~seconds
// Every other request now waits behind this one CPU-bound call.
The distinction that matters: I/O-bound work (waiting on disk, network, sockets) is already parallel because the waiting happens outside your thread. CPU-bound work (pure computation) is the problem, because it monopolises the one thread that runs JavaScript. Splitting it into setImmediate chunks helps latency a little but wastes wall-clock time and is fiddly. The real fix is a second thread.
Analogy. The main thread is a single cashier who is brilliant at handing tickets to the kitchen and moving on. But if a customer asks the cashier to personally cook a 20-minute meal, the whole queue stalls. A worker thread is a second cashier in a back room: you slide them the order, they cook, and the front cashier keeps serving everyone else.