OSSTube

Node.js Worker Threads: How I Stopped the Event Loop From Haunting Me

Technology
6 min read
A
Amit Sadaphal
6 min read

January 18, 2026

0

0

15

The Nightmare Begins: Event Loop Freeze

I shipped a Node API thinking it was all sunshine and rainbows, right? Traffic started climbing, and suddenly these CPU-intensive tasks showed up – image resizing, some crypto stuff, scoring models the data scientists cooked up – and my event loop just started choking; requests timing out, AWS t3.medium instances crying for help and all that good stuff. I was staring at Datadog at 3 AM, realizing I needed to actually *do* something about it. Turns out, `worker_threads` are the answer if you want real parallelism without rewriting everything in Go, but you gotta use them right.

A generic tech blog image about The Nightmare Begins: Event Loop Freeze
A generic tech blog image about The Nightmare Begins: Event Loop FreezeSource: AI Generated

The Base Camp: A Reusable Worker

Before you even *think* about diving into patterns, you need a solid, reusable worker. Trust me, you don't want to copy-paste that crap all over your codebase. This is the base I ended up with – it takes a function name and arguments, executes the function, and returns a result, or returns the error details. Simple. Clean. And it won't make you want to scream when debugging it at 2 AM. Here's the code I ended up using:

worker.js
1// worker.js
2const { parentPort, workerData } = require('node:worker_threads');
3
4async function heavyFizzBuzz(n) {
5  let c = 0;
6  for (let i = 0; i < n; i++) c += (i % 3 === 0 || i % 5 === 0) ? 1 : 0;
7  return c;
8}
9
10const ops = { heavyFizzBuzz };
11
12(async () => {
13  try {
14    const { op, args } = workerData;
15    const result = await ops[op](...args);
16    parentPort.postMessage({ ok: true, result });
17  } catch (err) {
18    parentPort.postMessage({ ok: false, error: { message: err.message, stack: err.stack } });
19  }
20})();
JAVASCRIPT

The Quick Fix: Single-Shot Offload

Need to hash a password *now*? Gotta compress a file *fast*? This is my go-to pattern for occasional, short CPU bursts that you don't want clogging up the main thread. It's fire-and-forget, but you better make sure the work actually *completes* or you will see problems down the line. I once forgot proper error handling and ended up with zombie processes eating all the memory.

singleShot.js
1const { Worker } = require('node:worker_threads');
2
3function runHeavy(op, ...args) {
4  return new Promise((resolve, reject) => {
5    const w = new Worker(require.resolve('./worker.js'), { workerData: { op, args }});
6    w.once('message', m => m.ok ? resolve(m.result) : reject(new Error(m.error.message)));
7    w.once('error', reject);
8    w.once('exit', code => { if (code !== 0) reject(new Error(`Worker exited ${code}`)); });
9  });
10}
11
12// usage…
JAVASCRIPT
Tags
Node.js
Worker Threads
Concurrency
Performance
JavaScript
A
About Amit Sadaphal

15 views

0 shares

Trending

navbarlogoimage
Mobile: +91 8826844273Email: [email protected]

OSSTube

About usPrivacy PolicyTerms

NEWSLETTER

If you wanted to know more details please share email with us...