Process and Workers
Process metadata, subprocesses, and worker threads for CPU-bound work. Results appear in the same fence: same-line // comments when short, multiline // blocks below the sample when not.
Search across all documentation pages
Process metadata, subprocesses, and worker threads for CPU-bound work. Results appear in the same fence: same-line // comments when short, multiline // blocks below the sample when not.
Read environment variables and CLI arguments from process.
const port = Number(process.env.PORT ?? 3000);
Number.isFinite(port) // true
const args = process.argv.slice(2);
Array.isArray(args) // trueSpawn a subprocess with streamed stdio - preferred over shell exec for safety.
import { spawn } from "node:child_process";
const child = spawn(process.execPath, ["-e", "console.log(1)"], {
encoding: "utf8" as any,
});
let out = "";
child.stdout?.on("data", (c) => { out += c; });
const code = await new Promise<number | null>((res) => child.on("close", res));
code // 0
out.trim() // "1"Run a binary and capture output as a promise without a shell.
import { execFile } from "node:child_process";
import { promisify } from "node:util";
const execFileAsync = promisify(execFile);
const { stdout } = await execFileAsync(process.execPath, ["-e", "console.log(1)"]);
stdout.trim() // "1"Offload CPU work to a worker thread to keep the event loop free.
import { Worker } from "node:worker_threads";
// const worker = new Worker(new URL("./cpu-job.js", import.meta.url));
// worker.postMessage({ n: 40 });
typeof Worker // "function"Inside a worker, talk to the parent via parentPort.
import { parentPort, isMainThread } from "node:worker_threads";
isMainThread // true in this file
// in worker: parentPort?.postMessage({ ok: true });Pass immutable init data when constructing a worker.
import { workerData } from "node:worker_threads";
// new Worker(file, { workerData: { jobId: "x" } });
// inside worker: workerData.jobId === "x"
typeof workerData // "object" | may be empty on mainKnow and optionally change the process working directory carefully.
import path from "node:path";
path.isAbsolute(process.cwd()) // true
// process.chdir("/tmp");Set exit codes for CLI success/failure conventions.
process.exitCode = 0;
process.exitCode // 0
// on failure: process.exitCode = 1;Read piped stdin as text for CLI tools.
import { Readable } from "node:stream";
const lines: string[] = [];
for await (const line of Readable.from(["a\n", "b\n"])) {
lines.push(String(line).trim());
}
lines // ["a", "b"]Share memory between workers with Atomics for advanced coordination.
const sab = new SharedArrayBuffer(4);
const view = new Int32Array(sab);
Atomics.store(view, 0, 7);
Atomics.load(view, 0) // 7fork is spawn specialized for Node children with IPC channel.
import { fork } from "node:child_process";
typeof fork // "function"
// const child = fork("./worker-entry.js");
// child.send({ type: "start" });Sample heap and RSS for quick diagnostics.
const m = process.memoryUsage();
m.rss > 0 // true
m.heapUsed > 0 // truelibuv pool size affects fs/crypto/dns concurrency - tune with UV_THREADPOOL_SIZE carefully.
// UV_THREADPOOL_SIZE=16 node app.js
// default pool size is 4
process.env.UV_THREADPOOL_SIZE ?? "4" // "4" unless setFail fast or log centralized handling for unhandled rejections in servers.
// process.on("unhandledRejection", (reason) => {
// console.error(reason);
// process.exit(1);
// });
typeof process.on // "function"Create entangled ports for structured clone messaging between threads.
import { MessageChannel } from "node:worker_threads";
const { port1, port2 } = new MessageChannel();
const seen: unknown[] = [];
port1.on("message", (m) => seen.push(m));
port2.postMessage({ hi: true });
await new Promise((r) => setImmediate(r));
seen
// [{ hi: true }]Stack versions: Node.js 24.18.0 (LTS line 24) · TypeScript 5.6+ · npm 10+
Reviewed by Chris St. John·Last updated Jul 18, 2026