Skip to content
Bill Liao
Go back

100 Node.js interview Questions and Answers

Edit page

Below is a practical Node.js interview guide, organized from fundamentals to advanced topics. It is especially useful for Senior Node.js / Full-Stack / Backend / Lead Engineer interviews.


1. Node.js Fundamentals

1. What is Node.js?

Answer:
Node.js is an open-source, cross-platform JavaScript runtime built on Chrome’s V8 JavaScript engine. It allows JavaScript to run outside the browser, primarily for server-side applications.

Node.js is particularly suited for:

Its architecture uses a single JavaScript thread with asynchronous, non-blocking I/O, allowing it to handle many concurrent connections efficiently.


Answer:

The main reasons include:


3. Is Node.js a programming language?

Answer:
No.

Node.js is a JavaScript runtime environment.

JavaScript is the programming language, while Node.js provides the runtime environment, APIs, libraries, and execution model needed to run JavaScript outside the browser.


4. What JavaScript engine does Node.js use?

Answer:
Node.js uses Google’s V8 JavaScript engine, originally developed for Google Chrome.

V8 compiles JavaScript into machine code and executes it efficiently.


5. What is npm?

Answer:
npm stands for Node Package Manager.

It is used to:

Example:

Bash

npm install express

6. What is package.json?

Answer:
package.json describes a Node.js project.

It commonly contains:

{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^5.0.0"
  }
}

It defines project metadata, dependencies, scripts, and configuration.


7. What is package-lock.json?

Answer:
package-lock.json records the exact dependency versions installed for a project.

It helps ensure reproducible installations across:


8. What is the difference between npm install and npm ci?

Answer:

npm install can update dependency versions according to the package version ranges.

npm ci installs exactly what is specified in package-lock.json.

npm ci is generally preferred in CI/CD because it provides deterministic installations.


9. What is the difference between dependencies and devDependencies?

Answer:

dependencies are required at runtime.

"dependencies": {
  "express": "^5.0.0"
}

devDependencies are primarily required during development or build/test processes.

"devDependencies": {
  "jest": "^30.0.0"
}

10. What is npx?

Answer:
npx executes npm packages without necessarily installing them globally.

For example:

Bash

npx create-next-app my-app

It is particularly useful for running CLI tools.


2. Node.js Architecture

11. Is Node.js single-threaded?

Answer:
The JavaScript execution model is primarily single-threaded, meaning JavaScript code normally runs on one main thread.

However, Node.js itself is not limited to one OS thread.

Node.js uses:

Therefore, saying “Node.js is single-threaded” is an oversimplification.


12. What is the event loop?

Answer:
The event loop allows Node.js to perform asynchronous operations without blocking the JavaScript thread.

Conceptually:

JavaScript
    ↓
Event Loop
    ↓
Async I/O
    ↓
Callback / Promise
    ↓
JavaScript

This enables Node.js to handle many concurrent I/O operations efficiently.


13. What is libuv?

Answer:
libuv is a C library used by Node.js to provide:

It is one of the core components behind Node.js’s asynchronous architecture.


14. How does Node.js handle asynchronous operations?

Answer:

A typical flow is:

Application
     ↓
Node.js API
     ↓
libuv
     ↓
OS / Thread Pool
     ↓
Completion
     ↓
Event Loop
     ↓
Callback / Promise

Node.js delegates appropriate operations and continues executing other JavaScript instead of waiting synchronously.


15. What is non-blocking I/O?

Answer:
Non-blocking I/O means Node.js can initiate an I/O operation and continue executing other work without waiting for the operation to finish.

Example:

fs.readFile("data.txt", (err, data) => {
  console.log(data);
});

console.log("Continue execution");

The second statement can execute before the file read completes.


16. What is blocking code?

Answer:
Blocking code prevents the JavaScript thread from processing other work.

For example:

JavaScript

const data = fs.readFileSync("large-file.txt");

While this operation executes, the main JavaScript thread cannot process other requests.


17. Why should CPU-intensive operations be avoided on the main Node.js thread?

Answer:
Because CPU-intensive JavaScript blocks the event loop.

For example:

while (true) {
  // CPU-intensive work
}

During this loop, Node.js cannot process other incoming requests.

Solutions include:


18. What are the phases of the Node.js event loop?

Answer:

Important phases include:

  1. Timers
  2. Pending callbacks
  3. Idle/prepare
  4. Poll
  5. Check
  6. Close callbacks

The exact internal behavior is more nuanced, but these phases explain how Node.js schedules different types of asynchronous work.


19. What is the difference between setTimeout() and setImmediate()?

Answer:

setTimeout() schedules a callback after a minimum delay.

setTimeout(() => {
  console.log("timeout");
}, 0);

setImmediate() schedules a callback for the check phase of the event loop.

setImmediate(() => {
  console.log("immediate");
});

Their relative execution order can depend on context, particularly whether they are scheduled from an I/O callback.


20. What is process.nextTick()?

Answer:
process.nextTick() schedules a callback to execute after the current operation completes but before the event loop proceeds to its normal phases.

process.nextTick(() => {
  console.log("next tick");
});

Excessive recursive use can starve the event loop.


3. Modules

21. What is a module in Node.js?

Answer:
A module is a reusable unit of code that encapsulates functionality.

Node.js supports two major module systems:


22. What is CommonJS?

Answer:
CommonJS is the traditional Node.js module system.

Example:

const express = require("express");

module.exports = myFunction;

23. What is ES Modules?

Answer:
ES Modules are the standardized JavaScript module system.

Example:

import express from "express";

export default myFunction;

Modern Node.js supports ESM natively.


24. What is the difference between CommonJS and ESM?

Answer:

CommonJSESM
require()import
module.exportsexport
Traditional Node.js modulesStandard JavaScript modules
Synchronous module loading semanticsSupports static module structure and top-level await

25. What is module.exports?

Answer:
module.exports defines what a CommonJS module exposes.

module.exports = {
  add,
  subtract
};

Another file can consume it using:

JavaScript

const math = require("./math");

26. What is the difference between exports and module.exports?

Answer:
Initially:

JavaScript

exports === module.exports

This works:

JavaScript

exports.foo = foo;

But this can break the reference:

JavaScript

exports = foo;

To replace the exported value, use:

JavaScript

module.exports = foo;

27. What is module caching?

Answer:
When a CommonJS module is loaded, Node.js caches it.

For example:

require("./config");
require("./config");

The second call normally returns the cached module rather than executing the module again.


28. What is __dirname?

Answer:
In CommonJS, __dirname contains the directory path of the current module.

JavaScript

console.log(__dirname);

29. What is __filename?

Answer:
__filename contains the absolute path of the current CommonJS module file.


30. How do you get the equivalent of __dirname in ESM?

Answer:
ESM does not provide __dirname directly.

A common approach is:

import { fileURLToPath } from "node:url";
import path from "node:path";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

4. Asynchronous Programming

31. What is a callback?

Answer:
A callback is a function passed to another function to be executed later.

fs.readFile("file.txt", (err, data) => {
  console.log(data);
});

32. What is callback hell?

Answer:
Callback hell occurs when deeply nested callbacks make code difficult to read and maintain.

Example:

doSomething(() => {
  doSomethingElse(() => {
    doAnotherThing(() => {
      // ...
    });
  });
});

Promises and async/await help solve this problem.


33. What is a Promise?

Answer:
A Promise represents the eventual result of an asynchronous operation.

It has three states:

Example:

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error));

34. What is async/await?

Answer:
async/await provides a cleaner syntax for working with Promises.

async function getUser() {
  try {
    const user = await fetchUser();
    return user;
  } catch (error) {
    console.error(error);
  }
}

35. Does async/await make code synchronous?

Answer:
No.

It makes asynchronous code look synchronous, but the underlying operation remains asynchronous.


36. What is Promise.all()?

Answer:
Promise.all() runs multiple promises concurrently and resolves when all succeed.

const [users, orders] = await Promise.all([
  getUsers(),
  getOrders()
]);

If one rejects, the returned Promise rejects.


37. What is Promise.allSettled()?

Answer:
Promise.allSettled() waits for every Promise to finish regardless of whether it succeeds or fails.

const results = await Promise.allSettled([
  task1(),
  task2(),
  task3()
]);

Useful when you need the result of every independent operation.


38. What is Promise.race()?

Answer:
Promise.race() settles as soon as the first Promise settles.

It can be useful for timeout patterns.


39. What is Promise.any()?

Answer:
Promise.any() resolves when the first Promise fulfills.

Rejected promises are ignored unless all promises reject.


40. How do you handle errors with async/await?

Answer:

Use try/catch:

try {
  const result = await service.call();
} catch (error) {
  console.error(error);
}

In an HTTP application, errors should also be propagated to centralized error-handling middleware or an appropriate framework mechanism.


5. Express.js

41. What is Express.js?

Answer:
Express is a minimalist Node.js web framework used to build:


42. What is middleware?

Answer:
Middleware is a function that executes during the HTTP request/response lifecycle.

Example:

app.use((req, res, next) => {
  console.log(req.method, req.url);
  next();
});

43. What does next() do?

Answer:
next() passes control to the next middleware or route handler.

If you don’t call next() and don’t send a response, the request may hang.


44. What is Express error-handling middleware?

Answer:
Express error middleware has four parameters:

app.use((err, req, res, next) => {
  console.error(err);

  res.status(500).json({
    error: "Internal Server Error"
  });
});

45. How do you create a REST API with Node.js?

Answer:

Example:

app.get("/users/:id", async (req, res) => {
  const user = await userService.findById(req.params.id);

  res.json(user);
});

A production API normally also includes:


46. What is the difference between app.use() and app.get()?

Answer:

app.use() registers middleware and can apply to multiple HTTP methods.

JavaScript

app.use("/api", middleware);

app.get() specifically handles GET requests.

JavaScript

app.get("/users", handler);

47. How do you handle CORS in Node.js?

Answer:
CORS can be configured using middleware or directly through response headers.

For example:

JavaScript

res.setHeader("Access-Control-Allow-Origin", "https://example.com");

In Express, a CORS middleware package is commonly used.


48. How do you validate API input?

Answer:
Use schema validation libraries such as:

Example conceptually:

JavaScript

const result = schema.safeParse(req.body);

Never assume client input is trustworthy.


49. How should authentication be implemented in Node.js?

Answer:
Common approaches include:

For enterprise systems, OAuth 2.0/OIDC with a trusted identity provider is often preferable to implementing authentication from scratch.


50. What is JWT?

Answer:
JWT stands for JSON Web Token.

It contains claims encoded into a signed token.

Typical structure:

header.payload.signature

JWTs are commonly used for stateless authentication and authorization.


6. Streams and Buffers

51. What is a Stream in Node.js?

Answer:
A Stream processes data incrementally rather than loading the entire dataset into memory.

Useful for:


52. What are the types of streams?

Answer:

Four major types:

  1. Readable
  2. Writable
  3. Duplex
  4. Transform

53. What is a Readable stream?

Answer:
A Readable stream produces data.

Example:

const stream = fs.createReadStream("large-file.txt");

stream.on("data", chunk => {
  console.log(chunk);
});

54. What is a Writable stream?

Answer:
A Writable stream consumes data.

Example:

const output = fs.createWriteStream("output.txt");

output.write("Hello");
output.end();

55. What is a Duplex stream?

Answer:
A Duplex stream can both read and write.

A TCP socket is a common example.


56. What is a Transform stream?

Answer:
A Transform stream modifies data as it passes through.

Examples:


57. What is a Buffer?

Answer:
A Buffer is a Node.js representation of binary data.

Example:

const buffer = Buffer.from("Hello");

console.log(buffer);

Buffers are commonly used for:


58. Why are streams important for large files?

Answer:
Without streams:

JavaScript

const data = await fs.promises.readFile("10GB-file");

The application may need to hold a huge amount of data in memory.

With streams:

File
 ↓
Chunk
 ↓
Process
 ↓
Chunk
 ↓
Process

Memory usage can remain much lower.


59. What is backpressure?

Answer:
Backpressure occurs when a data producer generates data faster than the consumer can process it.

Node.js streams provide mechanisms to handle this.

Example:

JavaScript

readable.pipe(writable);

The stream pipeline helps regulate data flow.


60. What is pipeline()?

Answer:
pipeline() connects streams and handles completion/error propagation more safely than manually chaining streams.

Example:

import { pipeline } from "node:stream/promises";

await pipeline(
  source,
  transform,
  destination
);

7. File System and Networking

61. How do you read a file asynchronously?

Answer:

import { readFile } from "node:fs/promises";

const data = await readFile("data.txt", "utf8");

62. What is the difference between fs.readFile() and fs.createReadStream()?

Answer:

readFile() loads the complete file into memory.

createReadStream() reads the file incrementally.

For large files, streams are generally preferable.


63. How do you create an HTTP server using Node.js?

Answer:

import http from "node:http";

const server = http.createServer((req, res) => {
  res.writeHead(200, {
    "Content-Type": "application/json"
  });

  res.end(JSON.stringify({ message: "Hello" }));
});

server.listen(3000);

64. What is the difference between HTTP and HTTPS?

Answer:
HTTPS is HTTP over TLS.

HTTPS provides:


65. What is a TCP socket?

Answer:
A TCP socket provides a bidirectional communication channel between applications over TCP.

Node.js provides TCP networking through the net module.


8. Databases

66. How does Node.js connect to databases?

Answer:
Node.js uses database drivers or libraries.

Examples:

ORM/query tools include:


67. What is connection pooling?

Answer:
A connection pool maintains reusable database connections.

Instead of:

Request → Create connection → Query → Close

you have:

Request
   ↓
Connection Pool
   ↓
Reusable Connection

This reduces connection overhead and improves performance.


68. Why shouldn’t every request create a new database connection?

Answer:
Creating connections repeatedly is expensive and can exhaust database resources.

Connection pooling provides controlled concurrency and connection reuse.


69. How do you prevent SQL injection in Node.js?

Answer:
Use parameterized queries or trusted ORM/query-builder mechanisms.

Bad:

JavaScript

db.query(`SELECT * FROM users WHERE id = ${id}`);

Better:

db.query(
  "SELECT * FROM users WHERE id = $1",
  [id]
);

70. How do you implement transactions?

Answer:
Use database transactions through the database driver or ORM.

Conceptually:

BEGIN
 ↓
Operation 1
 ↓
Operation 2
 ↓
COMMIT

If something fails:

ROLLBACK

9. Security

71. What are common Node.js security risks?

Answer:

Common risks include:


72. How do you protect against dependency vulnerabilities?

Answer:

Use:

Bash

npm audit

Also:


73. What is prototype pollution?

Answer:
Prototype pollution occurs when an attacker manipulates JavaScript object prototypes, potentially affecting many objects.

Unsafe object merging and untrusted input handling are common causes.


74. How do you store passwords securely?

Answer:
Never store plaintext passwords.

Use a password hashing algorithm designed for passwords, such as:

Passwords should be salted and hashed.


75. How do you manage secrets in Node.js?

Answer:
Don’t hard-code secrets.

Use:

Example:

JavaScript

const dbPassword = process.env.DB_PASSWORD;

76. What is rate limiting?

Answer:
Rate limiting restricts how many requests a client can make within a period.

Example:

100 requests / minute / IP

It helps protect APIs from:


77. What is Helmet?

Answer:
Helmet is middleware that helps configure various HTTP security headers for Express applications.


78. How do you prevent command injection?

Answer:
Avoid executing shell commands using untrusted input.

Prefer APIs such as:

JavaScript

spawn("command", ["safe", "arguments"]);

and validate input carefully.


10. Performance

79. How do you improve Node.js performance?

Answer:

Common techniques include:


80. How do you detect event-loop blocking?

Answer:
Use:

The goal is to identify long-running synchronous JavaScript or CPU-heavy operations.


81. What is clustering in Node.js?

Answer:
Clustering allows multiple Node.js processes to run, potentially using multiple CPU cores.

Conceptually:

             Load Balancer
                  |
       +----------+----------+
       |          |          |
    Worker     Worker     Worker
       |          |          |
     CPU        CPU        CPU

82. What are Worker Threads?

Answer:
Worker Threads allow JavaScript to execute in separate threads.

They are useful for CPU-intensive tasks such as:

Example:

JavaScript

import { Worker } from "node:worker_threads";

83. Worker Threads vs Cluster?

Answer:

Worker ThreadsCluster
Multiple threadsMultiple processes
Can share memory via SharedArrayBufferSeparate memory spaces
Good for CPU-intensive tasksGood for scaling server processes
Lower process overheadStrong process isolation

84. What is horizontal scaling?

Answer:
Horizontal scaling means running multiple instances of an application.

             Load Balancer
            /      |      \
         Node     Node     Node
        Server   Server   Server

This is often preferred for scalable Node.js APIs.


85. How would you scale a Node.js API to millions of requests?

Answer:

A possible architecture:

                    CDN
                     |
              Load Balancer
             /      |      \
          Node     Node     Node
           |        |        |
        Redis     Redis    Redis
             \      |      /
              Database

Key techniques:


11. Error Handling and Observability

86. How do you handle uncaught exceptions?

Answer:
An uncaught exception indicates an unexpected application failure.

Applications should:

  1. Log the failure
  2. Record diagnostics
  3. Stop accepting new work when appropriate
  4. Restart safely through the process manager/container platform

Do not blindly continue running a potentially corrupted process.


87. What is an unhandled Promise rejection?

Answer:
It occurs when a Promise rejects and there is no appropriate rejection handler.

Example:

someAsyncOperation()
  .catch(error => {
    console.error(error);
  });

Production applications should have deliberate rejection handling and monitoring.


88. How do you log in Node.js applications?

Answer:
Use structured logging.

Common choices include:

Example:

logger.info({
  userId,
  requestId
}, "User created");

Structured logs are easier to search and analyze.


89. What is distributed tracing?

Answer:
Distributed tracing tracks a request across multiple services.

Example:

API Gateway
   ↓
Node.js Service
   ↓
Payment Service
   ↓
Database

A trace ID connects the operations together.

OpenTelemetry is a common standard for implementing observability.


90. What metrics should you monitor in Node.js?

Answer:

Important metrics include:

A useful starting point is the RED method:


12. Advanced Node.js

91. What is garbage collection in Node.js?

Answer:
Node.js uses V8’s garbage collector to automatically reclaim memory that is no longer reachable.

Developers should still avoid retaining unnecessary references because excessive memory retention can cause memory leaks.


92. How do you diagnose a memory leak?

Answer:

Typical techniques include:

Typical symptoms:

Memory ↑
Memory ↑
Memory ↑
Process crashes

93. What is a memory leak in Node.js?

Answer:
A memory leak occurs when objects that are no longer logically needed remain reachable and therefore cannot be garbage collected.

Common causes:


94. What is the difference between spawn(), exec(), and fork()?

Answer:

APITypical Use
spawn()Run a process with streaming I/O
exec()Execute a command and collect output
fork()Start another Node.js process with IPC

For large command output, spawn() is generally more suitable than exec() because output can be streamed.


95. What is IPC?

Answer:
IPC means Inter-Process Communication.

Node.js processes can communicate using mechanisms such as:

child_process.fork() provides built-in IPC support between parent and child Node.js processes.


96. How would you design a production-ready Node.js microservice?

Answer:

A good architecture might look like:

                 API Gateway
                     |
              Load Balancer
                     |
              Node.js Service
             /       |       \
          Cache    Queue    Database
             \       |       /
              Observability

Important considerations:


97. What is graceful shutdown?

Answer:
Graceful shutdown allows a Node.js application to finish existing work before terminating.

Example:

process.on("SIGTERM", async () => {
  server.close(async () => {
    await database.close();
    process.exit(0);
  });
});

A production implementation should also stop accepting new work, close connections, drain queues where appropriate, and enforce a shutdown timeout.


98. How do you implement retries safely?

Answer:
Retries should be used carefully.

Good practices include:

Example:

Attempt 1 → 100ms
Attempt 2 → 200ms
Attempt 3 → 400ms
Attempt 4 → 800ms

Blind retries can amplify outages.


99. What is idempotency and why is it important?

Answer:
An operation is idempotent if executing it multiple times produces the same intended result as executing it once.

For example:

http

PUT /users/123

can be designed to be idempotent.

For payment APIs, idempotency keys are particularly important:

http

Idempotency-Key: abc123

If the client retries because of a network timeout, the server can recognize the previous request and avoid processing the payment twice.


100. How would you design a highly scalable Node.js system?

Answer:
I would start with the requirements rather than choosing Node.js components immediately.

A possible architecture:

                       ┌──────────────┐
                       │     CDN      │
                       └──────┬───────┘
                              │
                       ┌──────▼───────┐
                       │ API Gateway  │
                       └──────┬───────┘
                              │
                 ┌────────────┼────────────┐
                 │            │            │
            ┌────▼────┐ ┌────▼────┐ ┌────▼────┐
            │ Node.js │ │ Node.js │ │ Node.js │
            │ Service │ │ Service │ │ Service │
            └────┬────┘ └────┬────┘ └────┬────┘
                 │            │            │
                 └────────────┼────────────┘
                              │
                  ┌───────────┴───────────┐
                  │                       │
             ┌────▼─────┐           ┌────▼─────┐
             │   Redis  │           │  Kafka /  │
             │   Cache  │           │   Queue   │
             └──────────┘           └────┬──────┘
                                         │
                                  ┌──────▼──────┐
                                  │  Database   │
                                  └─────────────┘

I would focus on:

Application Layer

Scalability

Reliability

Data

Observability

Security

The key senior-level point is that Node.js scalability is not simply about making JavaScript execute faster. The real challenge is designing the surrounding distributed system so that the event-driven application remains responsive, observable, resilient, and horizontally scalable.


🔥 15 Node.js Questions Most Likely to Appear in a Senior Interview

If you’re interviewing for a Senior/Lead Node.js Engineer, prioritize these:

  1. Explain the Node.js event loop.
  2. Why is Node.js good for I/O-heavy applications?
  3. What happens when the event loop is blocked?
  4. Explain process.nextTick(), setImmediate(), and setTimeout().
  5. Explain Promises and async/await.
  6. Promise.all() vs Promise.allSettled() vs Promise.race() vs Promise.any().
  7. CommonJS vs ES Modules.
  8. Streams and backpressure.
  9. Worker Threads vs Cluster.
  10. How would you diagnose a memory leak?
  11. How would you scale Node.js horizontally?
  12. How would you design a production-grade Node.js API?
  13. How would you implement graceful shutdown?
  14. How would you make distributed operations idempotent?
  15. How would you troubleshoot a Node.js service with high latency and CPU usage?

⭐ The Senior-Level Interview Pattern

For senior interviews, don’t stop at “what is it?”

Interviewers increasingly ask:

“Why?” → “What happens internally?” → “What are the trade-offs?” → “How would you use it in production?”

For example:

Junior answer:

“Node.js is single-threaded.”

Senior answer:

“JavaScript execution is primarily single-threaded, but Node.js uses the event loop, libuv, OS asynchronous I/O, a worker pool, and optionally Worker Threads. The key scalability advantage is that the main JavaScript thread doesn’t synchronously wait on typical I/O. However, CPU-heavy JavaScript can still block the event loop, so those workloads need to be moved to workers or separate processes.”

That distinction is often what separates a Node.js developer from a senior backend engineer.


Edit page
Share this post:

Previous Post
100 Express.js interview Questions and Answers
Next Post
100 TypeScript interview Questions and Answers