Skip to content

Node.js Developer interview questions

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

See a Node.js Developer resume example

Practice with flashcards

Spaced repetition · Hunter Pass

Questions

Node.js is a JavaScript runtime built for executing JavaScript outside a web browser.

  • It uses the V8 engine to compile and run JavaScript.
  • It provides server-side APIs for files, networking, processes, and operating-system integration.
  • Its event-driven, non-blocking I/O model suits services that handle many concurrent I/O operations.

Why interviewers ask this: The interviewer checks whether you understand Node.js as a runtime rather than a language or framework.

V8 executes JavaScript, while libuv provides the event loop and cross-platform asynchronous I/O support.

  • V8 parses, compiles, optimizes, and runs JavaScript code.
  • libuv coordinates timers, networking readiness, and work delegated to its thread pool.
  • Node.js binds these components to JavaScript APIs such as fs, timers, and network modules.

Why interviewers ask this: A strong answer separates JavaScript execution from the I/O and event-loop infrastructure.

concurrencyjavascript

It means one event-loop thread normally executes a process's JavaScript callbacks one at a time.

  • Concurrent I/O can still progress through the operating system and libuv.
  • Some filesystem, DNS, crypto, and compression work uses the libuv thread pool.
  • Worker threads or child processes can provide additional JavaScript execution threads or processes when needed.

Why interviewers ask this: The interviewer checks whether you distinguish single-threaded JavaScript execution from the runtime's broader concurrency.

event-loop

The event loop is the mechanism that repeatedly runs ready callbacks and coordinates asynchronous work without blocking on each operation.

  • JavaScript starts work such as a timer or network request and registers what should happen when it is ready.
  • Node.js processes callback queues in defined phases.
  • Long synchronous JavaScript delays every other callback because the event-loop thread cannot run them simultaneously.

Why interviewers ask this: A strong answer connects asynchronous operations, callback queues, and the cost of blocking the main thread.

event-loop

The main phases are timers, pending callbacks, idle and prepare internals, poll, check, and close callbacks.

  • The timers phase runs eligible setTimeout and setInterval callbacks.
  • Poll receives I/O events and runs many I/O callbacks, while check runs setImmediate callbacks.
  • Close callbacks handle events such as a socket's close callback, with microtasks processed around callback execution rather than as a normal phase.

Why interviewers ask this: The interviewer evaluates whether you know the event loop as phased queues rather than one generic callback list.

The timers phase makes a callback eligible after its delay has elapsed but does not guarantee an exact execution time.

  • The delay is a minimum threshold rather than a scheduled wall-clock appointment.
  • Earlier synchronous work and other queued callbacks can postpone execution.
  • setInterval repeats eligibility at an interval, but its callbacks can also be delayed by event-loop load.

Why interviewers ask this: A strong answer avoids treating JavaScript timers as precise real-time scheduling.

event-loop

The poll phase retrieves new I/O events and runs eligible callbacks for many completed I/O operations.

  • It can wait for I/O when no callback is immediately ready and no scheduling rule requires moving on.
  • Its waiting time is influenced by timers and queued setImmediate callbacks.
  • Not every asynchronous API completes in poll, so the event-loop phases still matter.

Why interviewers ask this: The interviewer checks whether you understand poll as the core I/O phase without assigning every callback to it.

setImmediate schedules a callback for the check phase, while setTimeout schedules it for the timers phase after a minimum delay.

  • Their relative order from top-level code is not a reliable general guarantee.
  • When both are scheduled from the same I/O callback, setImmediate runs in the upcoming check phase before the zero-delay timer.
  • Choose based on the intended phase rather than assuming either API means run immediately.

Why interviewers ask this: A strong answer names the phases and avoids an oversimplified ordering claim.

concurrency

process.nextTick queues a callback to run after the current JavaScript operation finishes and before the event loop continues to another phase.

  • After an ordinary callback returns, Node.js drains the nextTick queue before Promise microtasks.
  • ESM evaluation and an already-running microtask checkpoint mean this is not a universal source-order guarantee.
  • Recursively scheduling nextTick callbacks can starve timers and I/O, so it should not replace ordinary asynchronous scheduling.

Why interviewers ask this: The interviewer evaluates whether you know nextTick priority and its starvation risk.

promises

Promise reactions run from the microtask queue after the current callback or script completes, before Node.js continues with more event-loop work.

  • then, catch, finally, and resumed await code are scheduled as microtasks.
  • Microtasks are not a separate libuv event-loop phase.
  • A long chain of microtasks can delay timers and I/O callbacks even though each step is asynchronous.

Why interviewers ask this: A strong answer places Promise callbacks between JavaScript turns without calling them an event-loop phase.

event-loop

Blocking the event loop prevents the process from running other JavaScript callbacks during that work.

  • CPU-heavy loops and synchronous I/O increase latency for unrelated requests in the same process.
  • Non-blocking APIs let the event loop serve other work while I/O is pending.
  • Large CPU tasks may belong in worker threads, child processes, or another service instead of the request thread.

Why interviewers ask this: The interviewer checks whether you connect synchronous work on the main thread to service-wide latency.

concurrency

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

  • Common users include many filesystem APIs, dns.lookup, crypto operations, and zlib.
  • Completion is reported back so the associated callback or Promise can continue on the event-loop thread.
  • Network socket I/O normally relies on operating-system readiness rather than one pool thread per connection.

Why interviewers ask this: A strong answer identifies representative thread-pool work without claiming all asynchronous work uses threads.

asynccallbacks

A callback is a function passed to another operation to be invoked when work completes or an event occurs.

  • The initiating function can return before an asynchronous callback runs.
  • The callback receives completion data, an error, or event-specific arguments according to the API.
  • Callbacks are also used for synchronous iteration, so the API contract determines whether invocation is asynchronous.

Why interviewers ask this: The interviewer checks whether you define callbacks by control flow without assuming every callback is asynchronous.

callbacks

An error-first callback receives the error as its first argument and success data in later arguments.

  • A null or absent first argument indicates that the operation succeeded.
  • A non-null error should normally end the success path and be handled or propagated.
  • Many older Node.js APIs follow the form callback(error, result), which can be adapted to Promises with utilities such as promisify.

Why interviewers ask this: A strong answer knows both the argument order and the required branching behavior.

callbacks

Callback hell is deeply nested asynchronous control flow that makes sequencing, errors, and cleanup difficult to follow.

  • Named functions and early returns can flatten callback-based code.
  • Promises express sequences through returned chains and central catch handling.
  • async and await provide sequential-looking syntax while preserving Promise-based asynchrony.

Why interviewers ask this: The interviewer checks whether you understand the maintainability problem rather than only recognizing nested indentation.

promises

A Promise is pending until it becomes fulfilled with a value or rejected with a reason.

  • Fulfillment and rejection are the two settled states.
  • Once settled, a Promise cannot change to another state or value.
  • Handlers can be attached before or after settlement and still run asynchronously as microtasks.

Why interviewers ask this: The interviewer evaluates whether you know the Promise lifecycle and asynchronous handler behavior.

promises

then handles fulfillment, catch handles rejection, and finally runs cleanup-like code after either outcome.

  • Each method returns a new Promise, enabling further composition.
  • A value returned from a handler fulfills the next Promise, while a thrown error rejects it.
  • finally normally preserves the previous value or error unless its callback throws or returns a rejected Promise.

Why interviewers ask this: A strong answer explains chaining semantics rather than describing the methods as simple callbacks.

promises

Returning from a then handler connects its result to the next Promise in the chain.

  • Returning a plain value fulfills the next step with that value.
  • Returning a Promise makes the chain wait for and adopt that Promise's outcome.
  • Forgetting the return can let the outer chain continue with undefined before nested work finishes.

Why interviewers ask this: The interviewer checks whether you understand how Promise composition preserves sequencing and errors.

promises

Promise.all fulfills when every input fulfills and rejects on the first observed rejection, while Promise.allSettled reports every outcome.

  • Promise.all preserves input order in its fulfilled result array.
  • Its early rejection does not automatically cancel the other underlying operations.
  • allSettled returns status objects for fulfilled and rejected inputs, which is useful when every result matters.

Why interviewers ask this: A strong answer distinguishes result collection, rejection behavior, and the absence of automatic cancellation.

async

An async function always returns a Promise for its eventual result.

  • Returning a plain value fulfills that Promise with the value.
  • Throwing inside the function rejects the returned Promise.
  • The function body may use await to suspend its own continuation without blocking the event-loop thread.

Why interviewers ask this: The interviewer checks whether you connect async functions to Promise return and rejection semantics.

Locked questions

  • 21

    What does await do?

    async
  • 22

    How are errors handled with async and await?

    async
  • 23

    What is an unhandled Promise rejection?

    promises
  • 24

    How does CommonJS define and load modules?

    modules
  • 25

    How do ECMAScript modules define and load modules in Node.js?

  • 26

    What are the main differences between CommonJS and ESM in Node.js?

    modules
  • 27

    How does Node.js decide whether a .js file is CommonJS or ESM?

    modules
  • 28

    How does module caching work in Node.js?

    cachingmodules
  • 29

    How do __dirname and __filename differ between CommonJS and ESM?

    modules
  • 30

    What is package.json used for?

    npm
  • 31

    How do dependencies, devDependencies, and peerDependencies differ?

    dependencies
  • 32

    What are npm scripts?

    npm
  • 33

    What does semantic versioning mean in an npm dependency range?

    dependenciesnpmversioning
  • 34

    Why is a package lockfile important?

    packaging
  • 35

    What is npx used for?

  • 36

    What does the built-in fs module provide?

  • 37

    What are path.join and path.resolve used for?

    joins
  • 38

    How does the built-in http module represent an HTTP server request and response?

    http
  • 39

    What is EventEmitter?

  • 40

    How do on, once, and removeListener differ on EventEmitter?

  • 41

    What are the main types of Node.js streams?

  • 42

    How can a readable stream deliver data?

  • 43

    What is backpressure in Node.js streams?

    backpressure
  • 44

    What is the difference between writable.write and writable.end?

  • 45

    What is a Buffer in Node.js?

  • 46

    How do text encodings affect Buffer conversion?

  • 47

    What is process.env?

    concurrency
  • 48

    Which useful information and controls does the process object expose?

    concurrency
  • 49

    What is middleware in Express?

    middleware
  • 50

    How does Express error-handling middleware differ from regular middleware?

    middleware
  • 51

    You are implementing POST /tasks in Express. How would you validate the request and return a correct creation response?

    validation
  • 52

    GET /users/:id currently returns 200 with null when no user exists. How would you fix the handler?

    fundamentals
  • 53

    How would you safely parse page and limit for GET /products?page=2&limit=20?

  • 54

    A PATCH /users/:id endpoint spreads req.body into the database update. How would you make it safe?

    databaseendpointsspread
  • 55

    An Express endpoint accepts very large JSON bodies, and malformed JSON becomes a generic 500 response. How would you fix it?

    endpointsgenerics
  • 56

    A protected Express route sees req.body as undefined, and its authentication check never runs. What middleware ordering would you use?

    authmiddlewarefundamentals
  • 57

    How would you implement an authentication guard that makes req.user available to a protected Express endpoint?

    authendpoints
  • 58

    Several endpoints return unrelated JSON shapes for similar successes and errors. How would you make their responses consistent?

    endpoints
  • 59

    A file upload endpoint accepts any number and size of files and sometimes exhausts memory. How would you fix it?

    memoryendpoints
  • 60

    You need validation for a new endpoint and may encounter either Fastify or Express in the codebase. How would you choose the validation approach?

    validationendpoints
  • 61

    A route awaits getUser(id) and then getOrders(id), but neither call depends on the other. How would you reduce its response time?

    async
  • 62

    Promise.all rejects while a route is loading several required records. How should the route handle that failure?

    promises
  • 63

    A dashboard can still render when one of five optional data sources fails. How would you collect the successful data and report individual failures?

  • 64

    Code starts createOrder() and chargePayment(order.id) in Promise.all, but payment needs the new order ID. How would you fix the flow?

    promises
  • 65

    You must process 100,000 files concurrently, but starting 100,000 Promises at once would overload memory and the filesystem. How would you limit concurrency?

    promisesconcurrencymemory
  • 66

    A service uses callback-based fs.readFile and another legacy error-first callback API. How would you make both usable with async and await?

    asynccallbacksapi
  • 67

    The condition if (isAllowed(user)) always passes because isAllowed is async. What is wrong, and how would you fix it?

    async
  • 68

    A saveUser function calls database.save(user) inside braces but returns undefined immediately. How would you fix the function so callers can await completion and receive failures?

    asyncfundamentalsdatabase
  • 69

    An external API request occasionally fails. How would you add retries without duplicating writes or retrying permanent failures?

    resilienceapi
  • 70

    How would you make a fetch request stop after three seconds while also allowing its caller to cancel it with AbortController?

  • 71

    A small settings file contains JSON. How would you load it without hiding malformed JSON errors?

  • 72

    A route currently uses readFile to send a multi-gigabyte archive. What would you change?

  • 73

    File compression uses source.pipe(gzip).pipe(destination) and sometimes hangs or misses an error. How would you fix it?

  • 74

    How would you download a large HTTP response to disk without buffering the whole body?

    http
  • 75

    You must process a large CSV export one record at a time. Would you split incoming chunks on newlines?

    concurrency
  • 76

    A small app occasionally leaves a half-written JSON state file after a crash. How would you make writes atomic enough?

    concurrency
  • 77

    An endpoint receives a filename and serves a file from an uploads directory. How would you prevent path traversal?

    endpoints
  • 78

    A report exporter calls writable.write(chunk) in a fast loop and memory keeps growing. How would you respect backpressure?

    backpressurememory
  • 79

    Cyrillic text becomes corrupted when read from a stream, while binary attachments must remain unchanged. How would you choose between strings and Buffers?

  • 80

    A file-reading endpoint should return not found for a missing file but currently turns every failure into 404. How would you fix it?

    endpoints
  • 81

    A call made with Node.js built-in fetch enters the success path when the external API returns 500. How would you fix the flow?

    api
  • 82

    An external API returns 200 and valid JSON, but a required user id is missing. What should your Node.js service do?

    api
  • 83

    Code logs await response.text() and then calls response.json(), which fails with a body-used error. How would you fix it?

    async
  • 84

    How would you safely build a URL with query parameters and add API authentication for an external request?

    queriesapiauth
  • 85

    An existing Node.js project already uses Axios through a shared API client, but built-in fetch is available. Which would you use for a new external integration?

    api
  • 86

    An external API returns 401 because an access token expired. How would you refresh the token without creating a retry loop?

    tokensapiresilience
  • 87

    How would you fetch all results from an external API that uses cursor pagination?

    pagination
  • 88

    Why should a service translate external API errors instead of passing the fetch or Axios error directly to its callers?

    api
  • 89

    How should errors from an async Express or Fastify route reach a centralized error handler?

    async
  • 90

    How would you keep an external API failure from leaking internal details through your Node.js endpoint?

    endpoints
  • 91

    A Node.js command reports an unhandled rejection and exits; how would you find and fix the cause without hiding the failure globally?

  • 92

    You inherit nested callbacks that read a file, parse it, and save a record; how would you refactor the flow?

    refactoringownershipcallbacks
  • 93

    An Express route sometimes throws 'Cannot set headers after they are sent'; how would you debug and fix it?

  • 94

    One request to an Express application stays pending forever with no response; what would you check?

  • 95

    An endpoint runs a large calculation loop and makes all other requests slow; how would you address it?

    endpoints
  • 96

    Why does an async forEach finish the outer function before its database updates complete, and how would you fix it?

    databaseasync
  • 97

    A production request fails intermittently; what context would you log to debug it without exposing secrets?

    secrets
  • 98

    How would you test a POST endpoint in Express or Fastify without starting a real server port?

    endpoints
  • 99

    Your application starts with an invalid PORT and later fails because a database URL is missing; how would you improve configuration handling?

    databaseconfig
  • 100

    How would you add graceful shutdown to a Node.js HTTP service that also has a database pool?

    databasehttplifecycle