How to Use Worker Threads for CPU-Intensive Tasks in Node.js
Worker threads let Node.js run CPU-intensive work on separate threads, so a heavy calculation no longer freezes your main event loop and blocks every other request. They are the right tool when the problem is computation, not I/O.
When you need worker threads
Node handles I/O beautifully on one thread, but CPU-bound work — image resizing, video processing, cryptography, complex parsing, large data crunching — blocks that thread while it runs. Everything else waits. Worker threads move that work off the main thread.
Worker threads vs the cluster module
- Cluster spreads separate requests across processes — good for scaling overall throughput. See the cluster module.
- Worker threads move CPU work within a request off the main thread — good for keeping one heavy task from blocking others.
A basic pattern
const { Worker } = require('node:worker_threads');
const worker = new Worker('./heavy-task.js', { workerData: input });
worker.on('message', result => { /* use result */ });
The heavy work runs in heavy-task.js on its own thread and posts the result back via parentPort.postMessage().
Sharing data efficiently
Threads communicate by message passing, which copies data. For large data, use a SharedArrayBuffer so threads share memory directly without copying. For repeated tasks, keep a pool of workers alive rather than spawning one each time — a worker pool library handles this cleanly.
Frequently asked questions
Are worker threads the same as multiple processes?
No. Threads run in the same process and can share memory via SharedArrayBuffer, which is lighter than separate processes. The cluster module uses processes; worker threads use threads within one process.
Should I create a worker per task?
For frequent tasks, no — spawning workers is not free. Use a worker pool that reuses a set of long-lived workers, dispatching tasks to whichever is free.
Do worker threads help with I/O?
Not really — Node already handles I/O asynchronously without blocking. Worker threads are specifically for CPU-bound work. If your bottleneck is I/O, look at your queries and caching instead.
Was this article helpful?