advanced
Worker threads
Move CPU-heavy work to worker threads with message passing, transfer lists, shared memory, and lifecycle control.
Worker threads run JavaScript in separate V8 isolates with message-passing communication — the right tool for CPU-bound JS, not a replacement for cluster scaling.
import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url), {
workerData: { primesUpTo: 500_000 },
});
worker.on('message', (result) => console.log(result));
} else {
const count = countPrimes(workerData.primesUpTo);
parentPort.postMessage({ count });
}
Transfer lists move ArrayBuffer ownership without copying. `SharedArrayBuffer` enables low-level shared memory but requires careful synchronization.
Workers have startup cost and separate memory — batch work per message instead of chatty fine-grained RPC.
On interviews: contrast workers (threads + shared process) with cluster (processes) and child processes; explain when workers beat async I/O.
Common pitfalls: passing large objects without transfer lists; sharing mutable state without Atomics; spawning workers per request under load.
Checklist:
- Use workers for CPU-heavy pure JS.
- Transfer ArrayBuffers when possible.
- Pool workers and reuse lifecycle.
- Keep messages coarse-grained.