How to Efficiently Handle CPU‑Intensive Tasks in Node.js

This article explains what CPU‑bound tasks are, why Node.js struggles with them, and presents three practical solutions—splitting work with setImmediate, offloading to child processes, and leveraging worker_threads—illustrated with a Fibonacci calculation example and complete code snippets.

Node Underground
Node Underground
Node Underground
How to Efficiently Handle CPU‑Intensive Tasks in Node.js

Node.js excels at I/O‑bound workloads but struggles with CPU‑intensive tasks. This guide explains what CPU‑bound tasks are, why Node.js is limited in this scenario, and offers three effective approaches.

1. Using setImmediate() to split tasks

This technique does not improve raw CPU utilization; instead it breaks a long‑running computation into smaller chunks executed via setImmediate(), allowing other events to run between chunks and improving responsiveness under load.

Drawbacks:

Low overall execution efficiency

Effective only when a single CPU‑bound task runs at a time

Increases development complexity

2. Using child processes

By moving the CPU‑heavy work to a separate process, the main event loop remains free. Child processes can fully utilize multiple CPU cores.

// worker.js
function fibonacci(num) {
  if (num <= 1) return num;
  return fibonacci(num - 1) + fibonacci(num - 2);
}
process.on('message', (message) => {
  process.send(fibonacci(message));
  process.exit(0);
});

In the main process you create the worker, send the input, and wait for the result:

const http = require('http');
const path = require('path');
const { fork } = require('child_process');
const port = 3000;
http.createServer((req, res) => {
  const url = new URL(req.url, `http://${req.headers.host}`);
  if (url.pathname === '/fibonacci') {
    const n = Number(url.searchParams.get('n'));
    const childProcess = fork(path.join(__dirname, 'fibonacci-fork'));
    childProcess.on('message', (message) => {
      res.writeHead(200);
      return res.end(`Result: ${message}`);
    });
    childProcess.send(n);
  } else {
    res.writeHead(200);
    return res.end('Hello World!');
  }
}).listen(port, () => console.log(`Listening on port ${port}...`));

3. Using worker_threads

Node.js LTS now includes the worker_threads module, allowing JavaScript to run in parallel threads. Compared with child processes, worker threads are lighter, start faster, consume less memory, and can share memory via SharedArrayBuffer.

Lower memory overhead

Faster startup

Ability to share memory between threads

These three methods provide practical ways to keep a Node.js server responsive while handling CPU‑intensive calculations.

Node.jsCPU-intensivesetImmediatechild_processworker_threads
Node Underground
Written by

Node Underground

No language is immortal—Node.js isn’t either—but thoughtful reflection is priceless. This underground community for Node.js enthusiasts was started by Taobao’s Front‑End Team (FED) to share our original insights and viewpoints from working with Node.js. Follow us. BTW, we’re hiring.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.