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 SharedArrayBuffer and 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:

NeedUse
Parallelize CPU-heavy JS, share memoryworker_threads
Use all cores for an I/O servercluster (or PM2)
Run an external binary / separate scriptchild_process