πΉ Introduction
Node.js is widely loved for its non-blocking I/O model. This makes it perfect for building scalable applications like APIs, chat apps, or real-time dashboards.
But hereβs the catch π Node.js is single-threaded by default.
That means if your app needs to perform CPU-intensive tasks like:
π Image processing
π Data analysis
π Password hashing
π€ Machine learning
β¦the event loop will get blocked β, and your app becomes slow or even unresponsive.
So, how do we fix this? π€
The answer is: Worker Threads.
πΉ What are Worker Threads in Node.js?
Worker Threads are a built-in multithreading feature introduced in Node.js v10.5.0 (and stable from v12+).
They allow us to:
Run JavaScript in parallel threads.
Offload heavy computations.
Keep the main event loop free to handle API requests and other async operations.
π Think of Worker Threads as dedicated helpers that run in the background while your main thread handles users.
πΉ Worker Threads vs Child Processes
Many developers confuse Worker Threads with Child Processes. Letβs clear this up π
Feature Worker Threads Child Processes
Memory Shared memory via SharedArrayBuffer Separate memory
Communication Fast, via postMessage Slower (via IPC)
Use case CPU-bound tasks Isolated tasks (like separate microservices)
π If you need parallel computation, use Worker Threads.
π If you need separate execution environments, use Child Processes.
πΉ Example 1: Basic Worker Thread
worker.js (Worker file)
const { parentPort } = require("worker_threads");
parentPort.on("message", (num) => {
let result = 0;
for (let i = 0; i < num; i++) {
result += i;
}
parentPort.postMessage(result);
});
main.js (Main thread)
const { Worker } = require("worker_threads");
function runWorker(num) {
return new Promise((resolve, reject) => {
const worker = new Worker("./worker.js");
worker.postMessage(num);
worker.on("message", resolve);
worker.on("error", reject);
worker.on("exit", (code) => {
if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
});
});
}
(async () => {
console.log("Main thread free for requests...");
const result = await runWorker(1000000);
console.log("Worker Result:", result);
})();
β
The worker thread calculates the sum.
β
The main thread remains free to handle HTTP requests.
πΉ Example 2: Image Processing with Worker Threads
Imagine your Node.js API allows users to upload profile pictures. If you resize images in the main thread, the API will hang. Instead, use a worker π
// imageWorker.js
const sharp = require("sharp");
const { parentPort } = require("worker_threads");
parentPort.on("message", async (filePath) => {
try {
await sharp(filePath)
.resize(200, 200)
.toFile("resized-" + filePath);
parentPort.postMessage("Image resized successfully!");
} catch (err) {
parentPort.postMessage("Error: " + err.message);
}
});
// server.js
const express = require("express");
const multer = require("multer");
const { Worker } = require("worker_threads");
const app = express();
const upload = multer({ dest: "uploads/" });
app.post("/upload", upload.single("image"), (req, res) => {
const worker = new Worker("./imageWorker.js");
worker.postMessage(req.file.path);
worker.on("message", (msg) => {
res.send(msg);
});
});
app.listen(3000, () => console.log("Server running on port 3000"));
π₯ Now your API can process images without blocking users.
πΉ Advantages of Worker Threads
βοΈ Utilizes multi-core CPUs effectively.
βοΈ Prevents event loop blocking.
βοΈ Easy message-based communication.
βοΈ Ideal for CPU-heavy tasks.
πΉ Disadvantages
β Higher memory usage compared to async functions.
β Too many workers = performance overhead.
β Not needed for I/O-bound tasks (use async/await instead).
πΉ Best Practices
β
Use Worker Threads for CPU-bound tasks only.
β
Implement a worker pool (using libraries like Piscina) for multiple workers.
β
Use SharedArrayBuffer if threads need to share memory.
β
Monitor worker performance with logging.
πΉ FAQs
Q1: Can Worker Threads access Node.js modules?
π Yes, they can use any Node.js module.
Q2: Are Worker Threads faster than async/await?
π Only for CPU-bound tasks. For I/O (like DB queries, API calls), async/await is better.
Q3: How many Worker Threads should I create?
π Ideally, equal to the number of CPU cores.
πΉ Conclusion
Worker Threads in Node.js are a powerful tool for improving performance when handling CPU-intensive tasks.
They:
β Keep your app responsive.
β Utilize multi-core processors.
β Allow parallel execution.
If youβre building high-performance applications like AI APIs, image processors, or big-data crunchers, Worker Threads are your best friend.
Top comments (0)