Initializing
Back to Patterns

Multi-Threaded CPU Scheduling in Node.js via Worker Threads

Node.jsConcurrencyWorker ThreadsPerformance

Node.js is notoriously single-threaded, making it incredibly fast for I/O operations but prone to event-loop blockage under heavy CPU calculations.

To execute intensive work without blocking client requests, use native Worker Threads.

---

The Thread Scheduler Pattern

Here is a clean implementation of a thread scheduling manager that spins up child worker processes and communicates via messaging channels:

typescript
import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
import path from 'path';

if (isMainThread) {
  /**
   * Main Process Event Loop Context
   * Dispatches computation payload to a clean system thread
   */
  export function scheduleHeavyTask(payload: any): Promise<any> {
    return new Promise((resolve, reject) => {
      const workerPath = path.resolve(__filename);
      
      const worker = new Worker(workerPath, {
        workerData: payload,
      });

      worker.on('message', (result) => {
        resolve(result);
      });

      worker.on('error', (err) => {
        reject(err);
      });

      worker.on('exit', (code) => {
        if (code !== 0) {
          reject(new Error(`Worker thread terminated with exit code: ${code}`));
        }
      });
    });
  }
} else {
  /**
   * Background Thread Context
   * Executes CPU computation isolations
   */
  const computePayload = workerData;
  
  // Simulated complex calculation
  let sum = 0;
  for (let i = 0; i < 1_000_000_000; i++) {
    sum += i * computePayload.multiplier;
  }

  // Communicate results back to main thread
  parentPort?.postMessage({ success: true, sum });
  process.exit(0);
}

---

Production Recommendations

  1. Avoid Over-allocation: Each Worker thread carries memory overhead (~10MB overhead per thread). Avoid spawning a new worker for every request; instead, implement a fixed Thread Pool queue.
  2. Channel Parity: Communication via .postMessage() copies data using the structured clone algorithm. Minimize data payload size to avoid memory thrashing.

Applied in Projects

Explore the real-world production systems and custom codebases where these engineering patterns are fully implemented.