Interview Q&A / Node.js

BeginnerIn-depth3 min readUpdated 2 Oct 2026

If Node.js is single-threaded, how does it handle thousands of requests at the same time?

SHORT ANSWER

Your JavaScript runs on one main thread, but slow work like network and file I/O is handed to the operating system or libuv's thread pool. The main thread never sits waiting; it keeps taking new requests and runs each callback when its I/O finishes.

Explain it simply

Think of a busy restaurant with one waiter. The waiter does not stand in the kitchen while your dosa is being made. They take your order, pass it to the kitchen, and go to the next table. When a dish is ready, the kitchen rings a bell and the waiter carries it out. One waiter can serve a whole floor because they never wait around.

Node.js works the same way. Your JavaScript code is the waiter: it runs on a single main thread. The kitchen is the operating system and a C library called libuv. When your code asks to read a file, query a database or call another API, Node hands that job off and moves on. When the job is done, a callback is put in a queue, and the event loop runs it as soon as the main thread is free.

Example

js
const http = require("node:http");
const fs = require("node:fs/promises");

http.createServer(async (req, res) => {
  // While this file is being read, Node is free to accept other requests.
  const data = await fs.readFile("./menu.json", "utf8");
  res.end(data);
}).listen(3000);

If 1,000 students open the page during a college fest registration rush, Node starts 1,000 file reads and keeps accepting connections. It does not need 1,000 threads, because none of the requests are blocking the main thread.

How it works

  • Network I/O (HTTP, database sockets) uses the operating system's own non-blocking mechanisms, such as epoll on Linux. No extra threads are needed.
  • Work the OS cannot do asynchronously (most file system calls, DNS lookups with dns.lookup, some crypto and zlib functions) goes to libuv's thread pool. It has 4 threads by default and can be changed with the UV_THREADPOOL_SIZE environment variable.
  • The event loop checks for finished work and runs the matching callbacks one at a time on the main thread.

So "single-threaded" is only true for your JavaScript. Node itself uses several threads behind the scenes.

Real-world use

Node is a good fit for I/O-heavy services: APIs, chat servers, live cricket score updates, and proxy layers that mostly wait on databases and other services.

Common mistakes

  • Doing heavy CPU work, like resizing images or a big loop, on the main thread. While it runs, every other request waits.
  • Using sync functions such as fs.readFileSync inside a request handler. They block the event loop.
  • Saying Node has "no threads at all". The thread pool exists; your JS just does not run on it.

What to say in the interview

"Node runs JavaScript on a single thread, but it uses non-blocking I/O. Network operations are handled by the operating system, and things like file system and some crypto calls go to libuv's thread pool, which has four threads by default. The main thread never waits; when I/O completes, its callback is queued and the event loop runs it. That is why Node handles many concurrent connections well, but it also means CPU-heavy work on the main thread blocks everyone, so I would move that to worker threads."

Follow-up questions

  • What kinds of operations use the libuv thread pool?
  • What happens if you run a 5-second loop inside a request handler?
  • How would you handle CPU-heavy work in Node?

Go deeper

Read these once the basics above feel easy.

If you fire many fs or crypto.pbkdf2 calls together, they queue up for the four pool threads, so the fifth call waits even though the main thread is idle. Raising UV_THREADPOOL_SIZE (set before the pool is first used) can help for file- or crypto-heavy services, but it does nothing for network I/O, which never uses the pool.

#nodejs#event-loop#libuv#concurrency

Related questions

Practise more Node.js questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open Node.js quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.