Advanced Concurrency and Parallelism
Explore worker threads, child processes, clustering, CPU-bound workloads, concurrency control, and graceful process management.
Worker Threads
Worker Threads allow JavaScript execution to occur in separate threads. They are useful for CPU-intensive work that would otherwise block the event loop.
Workers communicate through message passing and can optionally share memory through SharedArrayBuffer and synchronization primitives.
import { Worker, isMainThread, parentPort } from 'node:worker_threads';
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url));
worker.on('message', console.log);
worker.postMessage(10);
} else {
parentPort.on('message', (value) => {
parentPort.postMessage(value * value);
});
}- Worker Threads are useful for CPU-intensive JavaScript.
- Workers prevent CPU-heavy calculations from monopolizing the main event loop.
- Worker creation and communication have overhead, so workloads should justify their use.
When are Worker Threads most useful?
Child Processes and Cluster
Node.js can create child processes to execute other programs or isolate work. The cluster module can create multiple Node.js processes that share a server port, allowing applications to utilize multiple CPU cores.
Modern production deployments frequently use external process managers or container orchestration instead of relying exclusively on Node's built-in clustering features.
import { execFile } from 'node:child_process';
execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
console.error(error);
return;
}
console.log(stdout.trim());
});execFile() runs an executable with an argument array, avoiding the shell parsing behavior of exec().- Child processes provide process-level isolation and can execute external programs.
- Cluster uses multiple Node.js processes rather than multiple JavaScript threads.
- Production architecture should consider containers and orchestration as well.
What is a key distinction between Worker Threads and cluster processes?
Graceful Shutdown
Production Node.js services should handle shutdown signals such as SIGTERM. Graceful shutdown means stopping new work, allowing active requests to finish when appropriate, closing database connections, stopping consumers, and then exiting.
This is especially important in containerized environments where orchestration systems terminate processes during deployments and scaling operations.
const server = app.listen(3000);
process.on('SIGTERM', async () => {
console.log('Shutdown started');
server.close(async () => {
await database.close();
process.exit(0);
});
});- Handle termination signals explicitly in production services.
- Close external resources during shutdown.
- Graceful shutdown prevents dropped work and connection leaks.
Which signal is commonly used by container orchestrators to request graceful termination?