Skip to content

Node.js Developer interview questions

100 real questions with model answers and explanations for Node.js Developer candidates.

See a Node.js Developer resume example

Practice with flashcards

Spaced repetition · Hunter Pass

Questions

Node.js moves through phase-specific callback queues coordinated by libuv, with timers processed after poll in current releases.

  • Pending callbacks handle selected deferred system-operation callbacks.
  • Poll receives I/O readiness and runs many I/O callbacks, then check runs setImmediate callbacks.
  • Close callbacks run for abrupt handle closure, while nextTick and microtask queues are drained around JavaScript callback execution.

Why interviewers ask this: The interviewer checks whether your event-loop model reflects current Node.js phase behavior rather than an outdated circular diagram.

Macrotask is an informal name for event-loop work such as timers and I/O callbacks, while microtasks run at checkpoints between those callbacks.

  • Promise reactions and resumed await continuations use the V8 microtask queue.
  • process.nextTick has a separate Node.js queue with higher priority after ordinary callbacks.
  • Node.js drains these high-priority queues before continuing to another event-loop callback, so they can delay macrotask progress.

Why interviewers ask this: A strong answer distinguishes informal task categories from actual libuv phases and Node-specific nextTick behavior.

promisesconcurrency

After an ordinary callback returns, Node.js normally drains the nextTick queue before the V8 Promise microtask queue.

  • Callbacks scheduled by nextTick can enqueue more nextTick work before event-loop phases resume.
  • Promise handlers can enqueue further microtasks within the same checkpoint.
  • ESM evaluation and code already running inside a microtask mean this rule is not a universal source-order guarantee.

Why interviewers ask this: The interviewer evaluates whether you know the queue priority and the contexts that make simplistic ordering claims unsafe.

jobsconcurrency

process.nextTick runs before the event loop advances, setImmediate targets the check phase, and setTimeout targets timer processing after a delay threshold.

  • nextTick has the highest urgency and can starve I/O when scheduled recursively.
  • When both are created in one I/O callback, setImmediate runs in the upcoming check phase before a zero-delay timer.
  • From top-level code, setImmediate and a zero-delay timer have no universal relative-order guarantee.

Why interviewers ask this: A strong answer maps each API to its queue or phase and states ordering only where Node.js guarantees it.

The poll phase can wait for I/O when its queue is empty and no scheduling condition requires immediate progress elsewhere.

  • Ready I/O callbacks are processed from the poll queue.
  • A queued setImmediate causes the loop to proceed to check rather than wait indefinitely.
  • Upcoming timers bound how long poll can wait before timer processing is needed.

Why interviewers ask this: The interviewer checks whether you understand poll as both an I/O callback phase and a controlled waiting point.

Microtasks can starve other work because Node.js drains their queues before returning to event-loop phases.

  • Each Promise handler may enqueue another handler and keep the checkpoint busy.
  • Recursive process.nextTick is even more urgent and can prevent poll from running.
  • Breaking large work into bounded pieces scheduled with setImmediate allows timers and I/O to regain progress.

Why interviewers ask this: A strong answer connects starvation to queue-draining semantics rather than calling microtasks asynchronous and therefore harmless.

asyncconcurrency

The libuv thread pool runs selected blocking or CPU-intensive native operations away from the event-loop thread.

  • Many filesystem calls, dns.lookup, crypto, and zlib share the pool.
  • Pool saturation queues more of those operations even when the event-loop thread is idle.
  • Socket readiness usually uses operating-system event notification and does not consume one pool thread per connection.

Why interviewers ask this: The interviewer checks whether you distinguish thread-pool contention from event-loop scheduling.

event-loop

Event loop utilization estimates the proportion of elapsed time the event-loop thread was active rather than waiting for events.

  • A high value can indicate sustained JavaScript work or callbacks that keep the loop busy.
  • A low value does not prove healthy latency because work may be waiting in the libuv pool or an external dependency.
  • It complements delay histograms and application metrics rather than replacing them.

Why interviewers ask this: A strong answer understands what utilization measures and avoids treating it as a complete performance diagnosis.

event-loopconcurrency

Each worker thread has its own JavaScript isolate and event loop, so CPU work there does not execute on the main event-loop thread.

  • The main thread and workers communicate through messages or explicitly shared memory.
  • Asynchronous I/O on the main thread is usually efficient without workers.
  • Worker startup and communication have costs, so they suit substantial CPU-bound work rather than every callback.

Why interviewers ask this: The interviewer evaluates whether you connect event-loop isolation to an appropriate use of workers.

highWaterMark is a buffering threshold used to signal flow control, not a strict maximum amount of memory.

  • A readable stream may stop requesting more source data near the threshold.
  • A writable stream returns false from write when buffered data reaches the threshold.
  • In object mode the value counts objects, while byte-oriented streams generally count bytes.

Why interviewers ask this: A strong answer treats highWaterMark as a backpressure threshold and knows its unit changes in object mode.

backpressure

Backpressure propagates when a slower writable signals that upstream producers should pause until capacity returns.

  • write returning false tells a manual producer to wait for drain.
  • pipe pauses and resumes compatible readable sources based on downstream demand.
  • Ignoring the signal permits buffers to grow, increasing memory use and garbage-collection pressure.

Why interviewers ask this: The interviewer checks whether you understand backpressure as coordinated flow control across producers and consumers.

ci-cd

stream.pipeline connects streams while coordinating errors, closure, and teardown across the entire chain.

  • A failure in one stage destroys the related streams instead of leaving the rest running silently.
  • Its callback or Promise settles when the pipeline completes or fails.
  • The Promise form integrates with async functions and can accept an AbortSignal for cancellation.

Why interviewers ask this: A strong answer identifies lifecycle and error propagation as the main value beyond concise syntax.

stream.finished observes when a stream ends, finishes, closes, or fails according to its readable and writable sides.

  • It is useful when code needs completion notification without constructing a full pipeline.
  • The callback form returns a cleanup function for removing the listeners it installed.
  • The Promise utility from stream/promises enables the same lifecycle wait with await.

Why interviewers ask this: The interviewer evaluates whether you know how to observe stream completion without relying on one event that may cover only one side.

concurrency

A Transform stream implements a writable input side and a readable output side connected by transformation logic.

  • _transform receives an input chunk, encoding, and callback, then pushes zero or more output chunks.
  • The callback signals that the current chunk is finished and controls when the next input can be processed.
  • _flush can emit final buffered output before the readable side ends.

Why interviewers ask this: A strong answer covers the transform contract, flow control, and finalization hook.

Object mode lets stream chunks be JavaScript values other than null instead of byte-like data.

  • null remains reserved as the end-of-readable-stream signal, and readableObjectMode and writableObjectMode configure duplex sides independently.
  • highWaterMark counts objects rather than bytes in object mode.
  • Object mode is useful for record pipelines but does not serialize objects for network or file transport automatically.

Why interviewers ask this: The interviewer checks whether you understand object-mode units and its separation from serialization.

cork buffers small writes temporarily so uncork can flush them together to the underlying destination.

  • Batching can reduce system-call overhead for many small chunks.
  • Implementing _writev allows a custom writable to receive buffered chunks efficiently as a group.
  • uncork is commonly deferred with process.nextTick so writes from the current turn can be batched.

Why interviewers ask this: A strong answer connects corking to batching and the _writev optimization rather than treating it as general pausing.

async

Async iteration provides sequential chunk consumption with Promise-based waiting and natural use inside async functions.

  • The loop receives chunks only as they become available, respecting stream flow control.
  • Breaking early normally destroys the iterator-backed stream unless iterator options specify otherwise.
  • Errors from the stream reject the iteration and should be handled through the surrounding async error path.

Why interviewers ask this: The interviewer evaluates whether you understand both ergonomic consumption and early-exit lifecycle behavior.

Current Node.js can convert compatible readable and writable streams between Node.js and Web Streams representations.

  • Readable.toWeb and Readable.fromWeb bridge readable implementations.
  • Writable.toWeb and Writable.fromWeb provide the corresponding writable bridge.
  • Backpressure, cancellation, chunk types, and object-mode expectations still need compatible semantics at the boundary.

Why interviewers ask this: A strong answer knows the conversion APIs and does not assume the two stream models are behaviorally identical.

The cluster module starts multiple Node.js worker processes that can share incoming server connections.

  • Each worker is a separate process with its own V8 heap, event loop, and module state.
  • The primary process coordinates workers and connection distribution but does not create shared JavaScript memory.
  • Clustering uses multiple CPU cores for process-isolated request handling.

Why interviewers ask this: The interviewer checks whether you understand cluster as multi-process scaling rather than multithreading.

The cluster primary coordinates a shared server handle or distributes accepted connections to workers.

  • Workers can call listen with the same address through cluster-aware server setup.
  • The default scheduling policy on common platforms distributes connections among workers.
  • Application-level state is not shared merely because the workers serve one port.

Why interviewers ask this: A strong answer separates shared connection handling from isolated process memory.

Locked questions

  • 21

    What state-management constraints follow from using cluster workers?

  • 22

    How do worker_threads differ from cluster workers?

  • 23

    How are values transferred between worker threads?

    concurrency
  • 24

    What responsibilities come with SharedArrayBuffer and Atomics in worker threads?

    concurrency
  • 25

    What are the semantics of Promise.all for concurrent operations?

    promisesconcurrency
  • 26

    When is Promise.allSettled preferable to Promise.all?

    promises
  • 27

    What does Promise.race guarantee?

    promises
  • 28

    How does Promise.any differ from Promise.race?

    promises
  • 29

    Why is a concurrency limit often better than passing a huge input to Promise.all?

    promisesconcurrency
  • 30

    How does AbortController support cancellation in Node.js async APIs?

    resilienceasyncapi
  • 31

    What is the difference between operational errors and programmer errors in Node.js services?

  • 32

    What should a service assume after uncaughtException?

  • 33

    What does the unhandledRejection event represent?

  • 34

    Why use custom error classes and the cause option?

  • 35

    What problem does AsyncLocalStorage solve?

    async
  • 36

    How is memory divided between the V8 heap, stack, and external allocations?

    memorydata-structures
  • 37

    How does V8 garbage collection use object reachability and generations?

    gc
  • 38

    Which reference patterns commonly cause memory leaks in Node.js?

    memory
  • 39

    Why can Buffer-heavy applications use much more memory than heapUsed reports?

    memory
  • 40

    How does middleware ordering affect Express control flow?

    middleware
  • 41

    How do Fastify hooks and plugin encapsulation differ from a global Express middleware chain?

    hooksmiddlewareoop
  • 42

    Why place schema validation near the HTTP framework boundary?

    schemahttpvalidation
  • 43

    Why do Node.js database clients use connection pools?

    databasepooling
  • 44

    Why must a transaction keep one checked-out database connection?

    databasetransactions
  • 45

    What does Helmet provide in an Express application?

  • 46

    What design choices matter for API rate limiting?

    rate-limitingdesign
  • 47

    How do unit, integration, and end-to-end tests differ for a Node.js service?

    e2e
  • 48

    How should asynchronous tests signal completion?

    async
  • 49

    What are the trade-offs of mocks in Node.js tests?

    mocking
  • 50

    How can HTTP handlers be integration-tested without binding a public network port?

    http
  • 51

    How would you structure a Node.js API so HTTP, business logic, and data access remain testable?

    httpaccess-control
  • 52

    How would you design pagination for an API that serves a growing table?

    paginationdesign
  • 53

    How would you validate and normalize input at a Node.js API boundary?

    normalizationapivalidation
  • 54

    How would you make a create endpoint safe to retry?

    resilienceendpoints
  • 55

    How would you implement graceful shutdown for an HTTP API?

    httplifecycle
  • 56

    How would you attach a correlation ID to logs throughout one request?

    correlation
  • 57

    How would you enforce a deadline on an outbound HTTP call?

    estimationhttp
  • 58

    How would you process thousands of independent API calls without exhausting sockets or memory?

    memoryapiconcurrency
  • 59

    How would you prepare a Node.js API for horizontal scaling?

    scalingapi
  • 60

    When and how would you move work from an API request into a background queue?

    data-structures
  • 61

    How would you investigate a suspected Node.js memory leak with heap snapshots?

    memorysnapshotdata-structures
  • 62

    How would you interpret dominators and retaining paths in a heap snapshot?

    snapshotdata-structures
  • 63

    How would you diagnose event-loop blocking in a Node.js service?

  • 64

    How would you decide whether CPU-heavy work belongs in worker_threads?

  • 65

    How would you investigate a gradual latency degradation with stable traffic?

    latency
  • 66

    How would you distinguish database pool exhaustion from a slow database?

    database
  • 67

    How would you identify libuv thread-pool saturation?

    concurrency
  • 68

    How would you fix memory growth caused by a stream producer outrunning its consumer?

    memory
  • 69

    How would you design a useful load test for a Node.js API?

    designapiload-testing
  • 70

    How would you add graceful degradation when a noncritical dependency fails?

    dependencies
  • 71

    How would you size and configure a PostgreSQL pool for several Node.js replicas?

    postgresreplicationconfig
  • 72

    How would you prevent and detect database connection leaks?

    database
  • 73

    How would you remove an N+1 query pattern from an API endpoint?

    queriesn+1endpoints
  • 74

    How would you decide whether a slow PostgreSQL query needs an index?

    indexesqueriespostgres
  • 75

    How would you replace slow offset pagination on a large table?

    pagination
  • 76

    A PostgreSQL transaction intermittently fails with serialization errors or deadlocks. How would you retry it?

    transactionspostgreslocking
  • 77

    How would you implement cache-aside with Redis for an expensive read?

    rediscaching
  • 78

    How would you keep Redis cache entries consistent after writes?

    rediscaching
  • 79

    How would you build a centralized HTTP error handler?

    http
  • 80

    How would you handle an error after a streaming HTTP response has already started?

    streaminghttp
  • 81

    How would you handle partial failure when an endpoint calls several independent services?

    endpoints
  • 82

    How would you implement safe retries for an outbound request?

  • 83

    How would you keep a failed background job from disappearing or retrying forever?

    resiliencejobs
  • 84

    How would you design API errors for a client that must decide whether to retry?

    designresilienceapi
  • 85

    How would you validate JWTs in a Node.js API?

    validationapi
  • 86

    How would you implement secure cookie-based sessions?

    sessionscookies
  • 87

    How would you choose between JWT access tokens and server-side sessions?

    jwttokenssessions
  • 88

    How would you prevent mass-assignment bugs in an update endpoint?

    endpoints
  • 89

    How would you prevent SQL injection in a Node.js data layer?

    sqlinjection
  • 90

    How would you implement rate limiting across multiple API replicas?

    rate-limitingreplication
  • 91

    How would you configure CORS for a credentialed browser API?

    corsconfig
  • 92

    How would you store user passwords in a Node.js service?

    passwords
  • 93

    How would you choose a testing strategy for a new API endpoint?

    endpointstesting
  • 94

    How would you unit-test a service that depends on a repository and an email client?

    hypothesis-testing
  • 95

    How would you keep database integration tests isolated and repeatable?

    integrationdatabase
  • 96

    How would you integration-test a streaming file upload endpoint?

    streamingendpoints
  • 97

    How would you test that request cancellation stops downstream work?

    resilience
  • 98

    How would you test retry and timeout logic without slow real-time waits?

    resilience
  • 99

    How would you test compatibility with an external HTTP service without calling production?

    http
  • 100

    How would you verify that an API remains useful when Redis becomes unavailable?

    redisapi