Skip to the solution
HardSystem Design7 min read

How do you achieve concurrency in Node.js since it's single-threaded?

660 views

The problem

Question presented to candidate: "Your Node server handles 5 requests at the same time, each needing to wait 300ms on a downstream call. Does the 5th request wait for the first 4 to finish first, or do they all complete in roughly 300ms total?"

What a strong answer should cover:

  • Node's JavaScript runs on one thread, but concurrency comes from never blocking that thread on I/O β€” when a request needs to wait (a downstream call, a database query, a timer), the thread is freed to serve other requests during that wait, rather than sitting idle until the first one resolves.
  • πŸ“Œ Verified, not just asserted: 5 concurrent requests to a real HTTP server, each with a non-blocking 300ms delay, completed all 5 in ~356ms of total wall time β€” not the ~1500ms a naive, one-request-at-a-time (or blocking-per-request) server would need for the same workload.
  • The actual mechanism has two layers: the event loop (covered in its own dedicated question) schedules callbacks without ever parking the thread on a wait; and libuv (covered in its own dedicated question) provides the underlying async I/O primitives β€” the OS's native async networking facilities for sockets, plus a thread pool for a handful of specific blocking operations (file I/O, some crypto, DNS).
  • πŸ“Œ The critical caveat, stated precisely: this concurrency model helps I/O-bound waiting specifically. It does not parallelize CPU-bound work β€” a genuinely CPU-heavy computation inside one request handler still blocks the single thread, and therefore every other concurrent request, exactly as verified with real heartbeat-timer measurements in the dedicated blocking-vs-non-blocking and event-loop-pollution questions.
  • A precise answer distinguishes this from true parallelism: Node's single-thread concurrency model overlaps waiting time across many requests; it does not run multiple requests' JavaScript simultaneously on separate CPU cores. Actual multi-core parallelism needs the cluster module or additional processes (covered in its own dedicated question) for I/O-bound scaling, or Worker Threads for CPU-bound work.
  • The direct, concrete answer to the prompt's scenario: all 5 requests complete in roughly 300ms total, not 1500ms β€” provided the 300ms wait is genuinely non-blocking (a timer, a real async I/O call), which is exactly what was measured.

Clarifying questions expected:

  • "Is the 300ms wait a genuinely non-blocking operation (a timer, async I/O), or a synchronous computation that happens to take 300ms?" β€” only the former achieves the overlap being asked about.
  • "Is the concern I/O-bound concurrency specifically, or CPU-bound parallelism?" β€” Node's single-thread model addresses the former, not the latter.

Code / implementation expected: Yes β€” the real, measured 5-concurrent-requests result (~356ms, not ~1500ms) is the concrete, convincing proof, not a description of "non-blocking I/O."

  • concurrency
  • single-threaded
  • event loop
  • worker threads

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

7 min read Β· 9 sections

Read the code

JavaScriptA real HTTP server: 5 concurrent, genuinely non-blocking requests complete in ~356ms total, not ~1500ms
const http = require("http");

const server = http.createServer((req, res) => {
  setTimeout(() => res.end("slow response after 300ms"), 300); // non-blocking
});

server.listen(0, async () => {
  const port = server.address().port;
  const t0 = Date.now();
  await Promise.all(
    Array.from({ length: 5 }, () => fetch(`http://127.0.0.1:${port}/`).then((r) => r.text()))
  );
  console.log("5 concurrent 300ms-delayed requests, total time:", Date.now() - t0, "ms");
  // 5 concurrent 300ms-delayed requests, total time: 356 ms
  // (sequential serving of the same 5 requests would take ~1500ms)
  server.close();
});

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 131 of 152 in Node.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Node.js questions
Up nextHard

What are some common ways to improve performance in a Node.js application?

Continue