HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
3 Topics
Chapter•100 Minutes

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.

Basic Worker Thread
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);
  });
}
💡 The main thread creates a worker and sends it data. The worker performs CPU work and sends the result back.
Key Takeaways
  • 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.
Knowledge Check

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.

Running a Child Process
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().
Key Takeaways
  • 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.
Knowledge Check

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.

Graceful HTTP Shutdown
const server = app.listen(3000);

process.on('SIGTERM', async () => {
  console.log('Shutdown started');

  server.close(async () => {
    await database.close();
    process.exit(0);
  });
});
💡 The process stops accepting new connections, closes the HTTP server, releases resources, and exits.
Key Takeaways
  • Handle termination signals explicitly in production services.
  • Close external resources during shutdown.
  • Graceful shutdown prevents dropped work and connection leaks.
Knowledge Check

Which signal is commonly used by container orchestrators to request graceful termination?