I worker thread consentono a Node di eseguire JavaScript su thread separati con vero parallelismo — risolvendo il limite maggiore di Node: il lavoro CPU-intensivo che blocca l'unico main thread (e quindi tutte le richieste). Usali per calcoli pesanti, non per I/O (che l'event loop gestisce già in modo efficiente).
Il problema che risolvono
// ❌ this CPU-heavy work BLOCKS the event loop → all requests freeze for its duration
app.get("/hash", (req, res) => {
const result = expensiveComputation(); // e.g. heavy crypto, image processing
res.json(result); // meanwhile, no other request can be handled
});
Node esegue il tuo JS su un thread. Un calcolo sincrono lungo blocca tutto — l'event loop non può elaborare altre richieste finché non finisce. I worker thread spostano quel lavoro dal main thread.
Utilizzo di un worker thread
// main.js
import { Worker } from "worker_threads";
function runHeavyTask(data) {
return new Promise((resolve, reject) => {
const worker = new Worker("./worker.js", { workerData: data }); // runs on a NEW thread
worker.on("message", resolve); // receive the result
worker.on("error", reject);
worker.on("exit", (code) => { if (code !== 0) reject(new Error(`exit ${code}`)); });
});
}
// the main thread stays free to handle other requests while this runs
const result = await runHeavyTask({ numbers: [...] });
// worker.js — runs in parallel, on its own thread
import { workerData, parentPort } from "worker_threads";
const result = expensiveComputation(workerData); // doesn't block the main thread
parentPort.postMessage(result); // send the result back
Il worker funziona indipendentemente; il main thread continua a servire le richieste e ottiene il risultato tramite un messaggio quando è fatto.
Quando utilizzare (e non)
✓ USE for CPU-bound work: image/video processing, encryption, compression,
big data parsing, complex calculations, ML inference
✗ DON'T use for I/O (DB, files, HTTP) — the async event loop already handles
that efficiently; a worker would add overhead for no benefit
La regola: worker per CPU-bound, event loop per I/O-bound.
Worker thread vs child_process vs cluster
worker_threads → share memory (efficient data passing), in-process threads — CPU work
child_process → separate OS processes, run other programs — heavier isolation
cluster → fork the whole server across CPUs — scale request handling
Perché è importante
I worker thread affrontano il punto debole fondamentale di Node — i compiti CPU-bound bloccano l'event loop single-threaded e congelano tutte le richieste simultanee.
Sapere come offloadare il calcolo pesante a un worker (mantenendo il main thread responsivo), e crucialmente quando usarli (solo CPU-bound, mai per I/O), è quello che consente a un servizio Node di gestire elaborazioni pesanti occasionali senza sacrificare la concorrenza che rende Node prezioso.
Per il pooling dei worker in production, librerie come Piscina gestiscono efficientemente un thread pool.
