isMainThread
Tells you whether the current code is running on the main thread or inside a worker.
worker_threads.isMainThread- Added in Node.js v10.5.0
Return value
<boolean>true if this code is not running inside a Worker thread, false if it is.
A read-only boolean, fixed for the lifetime of the thread. It is true in the process's original thread and false in every Worker, however deeply nested.
When to reach for it
Two situations dominate. The first is the single-file worker pattern: one module contains both the code that spawns the thread and the code the thread runs, and isMainThread picks the branch. That keeps a small piece of parallel work in one file instead of two, and it is why new Worker(__filename) is such a common sight.
The second is defensive: library code that must not start servers, open databases, install signal handlers or read process.argv when it happens to be loaded inside a worker. Wrapping that startup in if (isMainThread) stops it running once per thread.
What trips people up
- It says nothing about clustering. Under
node:cluster, every worker process has its own main thread, soisMainThreadistruein all of them. Usecluster.isPrimaryfor that question. - It is not the inverse of
has a parent
in nested setups only in the sense you expect: a worker that spawns another worker is stillfalsein both. - Checking
parentPort !== nullis equivalent but noisier; prefer this flag for readability.
Example
const { Worker, isMainThread, parentPort } = require('node:worker_threads');
if (isMainThread) {
console.log('main thread:', isMainThread);
const worker = new Worker(__filename);
worker.on('message', (msg) => console.log('from worker:', msg));
worker.on('exit', () => console.log('done'));
} else {
parentPort.postMessage(`inside worker: ${isMainThread}`);
}
// Prints:
// main thread: true
// from worker: inside worker: false
// doneWhen to use it
- Put the spawner and the thread body in one file using new Worker(__filename)
- Stop a module from binding a port or opening a database once per thread
- Log or tag output with which thread produced it
- Skip CLI argument parsing when a module is loaded inside a worker
Frequently asked questions
How do I check if my code is running inside a worker thread?
Read isMainThread from node:worker_threads — it is false inside any Worker and true in the process's original thread. It is a plain boolean fixed at startup, so you can cache it or destructure it once at module scope.
Is isMainThread false in a cluster worker?
No. A cluster worker is a separate process whose own main thread reports isMainThread as true. Use cluster.isPrimary to distinguish the primary process from forked ones, and isMainThread only for threads inside a single process.
What is the difference between isMainThread and threadId === 0?
They agree in practice — the main thread always has threadId 0 — but isMainThread states the intent directly and is the documented way to test it. Use threadId only when you actually need to identify or label a specific thread.
More examples
Keeping module side effects out of workers
The same module is imported on both sides, but the listen() call is fenced off. Without the guard, every spawned thread would try to bind port 3000 and all but the first would fail with EADDRINUSE — a confusing error, because nothing in the worker's own code mentions a server.
// server.js — loaded by both the main thread and every worker
const { isMainThread } = require('node:worker_threads');
const http = require('node:http');
const routes = new Map([['/health', () => 'ok']]);
function start(port) {
const server = http.createServer((req, res) => {
const handler = routes.get(req.url);
res.end(handler ? handler() : 'not found');
});
server.listen(port);
return server;
}
// Only the main thread should bind a port. A worker that imports this
// module for `routes` must not accidentally start a second listener.
if (isMainThread) {
start(3000);
console.log('listening on 3000');
} else {
console.log('loaded in a worker; server not started');
}
module.exports = { routes, start };isMainThread is not cluster.isPrimary
A cluster worker is a whole separate process, and inside it isMainThread is still true with threadId 0, because it is the main thread of that process. The two flags answer different questions: cluster.isPrimary is about processes, isMainThread is about threads within one process. Mixing them up produces code that forks endlessly or never forks at all.
const cluster = require('node:cluster');
const { isMainThread, threadId } = require('node:worker_threads');
if (cluster.isPrimary) {
cluster.fork();
console.log('primary -> isPrimary:', cluster.isPrimary, 'isMainThread:', isMainThread);
} else {
console.log('forked -> isPrimary:', cluster.isPrimary, 'isMainThread:', isMainThread, 'threadId:', threadId);
process.exit(0);
}
// Prints:
// primary -> isPrimary: true isMainThread: true
// forked -> isPrimary: false isMainThread: true threadId: 0
Discussion