worker_threads vs cluster vs child_process — when do you use each?
3 minadvancednodejsworker-threadsclusterchild-processscaling
Quick Answer
worker_threads run JavaScript on additional threads sharing memory (via SharedArrayBuffer) — best for CPU-bound work inside one process. cluster forks multiple Node processes sharing a server port to use all CPU cores for I/O-bound servers. child_process spawns arbitrary external processes/commands.
Detailed Answer
Answer: All three add parallelism, but for different needs.
worker_threads — real threads within a single process:
- Each has its own V8 isolate and event loop, but they can share memory via
SharedArrayBufferand pass messages. - Best for CPU-bound JavaScript (parsing, compression, ML inference) without spinning up whole processes.
const { Worker } = require('worker_threads');
const w = new Worker('./cpu-task.js', { workerData: input });
w.on('message', result => { /* ... */ });
cluster — forks multiple Node processes (workers) that share a listening socket:
- Lets an I/O-bound server use all CPU cores (one process per core), since a single process only uses one core for JS.
- Processes are isolated (no shared memory); the OS/round-robin load-balances connections.
- In production this is often handled by a process manager (PM2) or the platform (containers behind a load balancer).
const cluster = require('cluster');
if (cluster.isPrimary) {
for (let i = 0; i < os.cpus().length; i++) cluster.fork();
} else {
http.createServer(handler).listen(3000);
}
child_process — spawn any external program or another Node script:
spawn(streams, long-running),exec(buffered, shell commands),fork(a Node child with an IPC channel).
const { spawn } = require('child_process');
spawn('ffmpeg', ['-i', 'in.mp4', 'out.webm']);
Choosing:
| Need | Use |
|---|---|
| Parallelize CPU-heavy JS, share memory | worker_threads |
| Use all cores for an I/O server | cluster (or PM2) |
| Run an external binary / separate script | child_process |