Backend & Node.js · APIs, data and failure
Is Node.js single-threaded? What does that actually mean?
Short answer
Your JavaScript runs on one thread, but the runtime is not strictly single-threaded. libuv maintains a thread pool for file system, DNS and crypto work, and worker threads can run JavaScript in parallel.
The single-threaded claim refers to the JavaScript execution context. Only one piece of JavaScript runs at a time, so there are no data races between callbacks on the main thread. The process still has multiple OS threads: the event loop, the libuv thread pool, garbage collection helpers and any workers you create.
import { readFile } from "node:fs/promises";
import { pbkdf2 } from "node:crypto";
async function load() {
const config = await readFile("config.json", "utf8");
console.log(config.length);
}
pbkdf2("password", "salt", 310000, 32, "sha256", (error, key) => {
if (error) throw error;
console.log(key.length);
});
load();What runs where
- JavaScript callbacks and module evaluation run on the main thread
- The libuv pool defaults to four threads for file system, DNS and crypto operations
- UV_THREADPOOL_SIZE changes the pool size but does not help CPU-bound JavaScript
- worker_threads run JavaScript on separate threads with message passing
- child processes run separate Node instances with their own memory
The model is efficient when work is I/O-bound because waiting does not consume a JavaScript thread. It struggles when a single request does heavy computation, because that computation blocks every other request on the same process.
Follow-ups you should expect
Interviewers use these to check whether the first answer was understanding or memorisation.
- 1If Node is single-threaded, how does it handle concurrent requests?
- 2What is the libuv thread pool used for?
- 3How do you handle CPU-bound work in Node?
- 4Does increasing UV_THREADPOOL_SIZE fix a slow JSON parser?
Say it in the interview
The JavaScript execution is single-threaded, so one callback runs at a time. But Node is not single-threaded as a process. libuv uses a thread pool for file, DNS and crypto work, and worker threads can execute JavaScript in parallel. The model is great for I/O because waiting is offloaded, but CPU-heavy work still blocks the main thread unless I move it to workers or separate processes.
Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.
Related questions
Reading is step one
Now say it out loud.
Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Backend & Node.js mock interview and get scored feedback on depth, clarity and confidence.