Node.js Interview Questions — Junior to Senior
60 Node.js interview questions covering the event loop, async patterns, Express architecture, database integration, security, and performance.
60 questions from junior to senior level. The most common Node.js interview topics — with the depth interviewers actually want.
Core Node.js & Event Loop
1. What is Node.js and how is it different from browser JavaScript?
Node.js is a JavaScript runtime built on Chrome's V8 engine. Unlike browser JS, Node has no DOM or browser APIs. Instead it has access to the file system, network, OS, and process — via built-in modules (fs, http, os, path, crypto). It's designed for server-side use.
2. What is the event loop?
The mechanism that allows Node.js to perform non-blocking I/O despite being single-threaded. While waiting for I/O (file reads, network), Node registers callbacks and continues executing other code. When the I/O completes, the callback is queued and executed in a future loop iteration.
The loop has phases: timers → pending callbacks → idle → poll (waiting for I/O) → check (setImmediate) → close callbacks.
3. What is the difference between setTimeout, setImmediate, and process.nextTick?
process.nextTick— runs before the next event loop iteration, before any I/O. Highest priority.setImmediate— runs in the check phase, after I/O callbacks.setTimeout(fn, 0)— runs in the timers phase, but never beforesetImmediatewhen inside an I/O callback.
I/O callback completes → nextTick queue → setImmediate → setTimeout(0)4. What does it mean that Node.js is single-threaded?
JavaScript execution runs on a single thread — no parallel execution of JS code. However, I/O operations are handled by the C++ libuv thread pool under the hood. CPU-heavy work blocks the event loop; async I/O does not.
5. How does Node.js handle CPU-intensive tasks without blocking?
By offloading to worker threads (worker_threads module) or child processes (child_process.fork()). The main thread delegates the work and continues handling requests while workers run in parallel.
6. What is libuv?
The C++ library that powers Node's event loop and async I/O. It provides the thread pool (for file system, DNS, crypto), timers, and the cross-platform async I/O abstraction that V8 uses.
7. What is a callback in Node.js and what is "callback hell"?
A callback is a function passed as an argument, called when an async operation completes. "Callback hell" is deeply nested callbacks that become impossible to read:
fs.readFile('a.txt', (err, data1) => {
fs.readFile('b.txt', (err, data2) => {
fs.writeFile('c.txt', data1 + data2, (err) => {
// 3 levels deep — and it gets worse
});
});
});Fixed with Promises or async/await.
8. What is the difference between Promises and async/await?
They're the same underlying mechanism. async/await is syntactic sugar over Promises that makes async code read like synchronous code. await pauses execution of the async function until the Promise resolves — without blocking the event loop.
9. What happens when you await inside a forEach loop?
The awaits don't work as expected — forEach doesn't wait for async callbacks:
// WRONG — all 3 run concurrently, forEach doesn't await
items.forEach(async (item) => { await processItem(item); });
// CORRECT — sequential
for (const item of items) { await processItem(item); }
// CORRECT — parallel
await Promise.all(items.map(item => processItem(item)));10. What is Promise.all vs Promise.allSettled vs Promise.race?
Promise.all— resolves when all resolve; rejects as soon as any rejectsPromise.allSettled— always resolves; returns array of{ status, value/reason }for eachPromise.race— resolves/rejects with the first to settle (used for timeouts)Promise.any— resolves with the first to succeed; rejects only if all reject
Express & API Design
11. What is middleware in Express?
A function with signature (req, res, next) that runs before the route handler. It can read/modify req and res, run code, call next() to pass control, or terminate the request by calling res.send()/res.json().
12. How does error handling work in Express?
Error-handling middleware has 4 parameters: (err, req, res, next). Express identifies it by arity. Call next(err) from any middleware to skip to the error handler. Register it last.
13. What is express.Router() used for?
Creates a mini-Express instance that handles routes. Used to group related routes into separate files and mount them at a path prefix: app.use('/api/products', productRouter).
14. How do you validate request body in Express?
With a validation library like Zod or Joi in a middleware. Parse req.body against a schema; if invalid, respond with 400 and the field errors. Replace req.body with the parsed (and transformed) data so controllers get clean, typed data.
15. What is the difference between req.params, req.query, and req.body?
req.params— URL path segments:/users/:id→req.params.idreq.query— URL query string:/users?page=2→req.query.pagereq.body— HTTP request body (JSON/form data), requires body-parsing middleware
16. How do you handle CORS in Express?
npm install corsimport cors from 'cors';
app.use(cors({
origin: ['https://myapp.com', 'http://localhost:4200'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true, // allow cookies
}));17. What HTTP status codes should a REST API return?
200 OK— successful GET, PUT, PATCH201 Created— successful POST that created a resource204 No Content— successful DELETE400 Bad Request— validation error, invalid input401 Unauthorized— not authenticated403 Forbidden— authenticated but not permitted404 Not Found— resource doesn't exist409 Conflict— duplicate entry, optimistic lock failure422 Unprocessable Entity— business logic validation failed429 Too Many Requests— rate limited500 Internal Server Error— unexpected server error
18. How do you implement pagination in a REST API?
Two approaches: offset/limit and cursor-based. Offset: ?page=2&pageSize=20 → skip: (page-1)*pageSize, take: pageSize. Cursor: ?cursor=lastId → where: { id: { gt: cursor } }, take: 20. Cursor is more performant for large datasets.
Authentication & Security
19. What is JWT and how does it work?
JSON Web Token — a base64-encoded, signed token with three parts: header.payload.signature. The server signs the payload with a secret. Any holder can decode the payload (it's not encrypted), but only the server can verify the signature. Never store sensitive data in a JWT payload.
20. What is the difference between authentication and authorization?
Authentication: verifying identity ("who are you?"). Authorization: verifying permissions ("what are you allowed to do?"). JWT handles authentication; role/permission checks handle authorization.
21. Why should refresh tokens be stored in HttpOnly cookies?
HttpOnly cookies can't be accessed by JavaScript — XSS attacks can't steal them. Access tokens (short-lived, in memory) can be stolen by XSS but expire quickly. Refresh tokens (long-lived) should be protected from XSS.
22. What is bcrypt and why use it for passwords?
A password hashing function designed to be slow (configurable work factor). Slowness makes brute-force attacks expensive — an attacker who steals your DB can't crack passwords quickly. Never use MD5, SHA1, or SHA256 for passwords — they're designed to be fast.
23. What is CSRF and how do you prevent it?
Cross-Site Request Forgery — an attacker tricks a logged-in user's browser into making requests to your API using their cookies. Prevention: use SameSite=strict on cookies, or require a CSRF token header that the attacker's site can't set.
24. How do you prevent SQL injection in Node.js?
Use parameterised queries or an ORM. Never interpolate user input into SQL strings:
// VULNERABLE
db.query(`SELECT * FROM users WHERE email = '${email}'`);
// SAFE — parameterised
db.query('SELECT * FROM users WHERE email = $1', [email]);
// SAFE — ORM
prisma.user.findUnique({ where: { email } });25. What HTTP security headers should your API set?
import helmet from 'helmet';
app.use(helmet()); // sets X-Content-Type-Options, X-Frame-Options, HSTS, etc.Key headers: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Strict-Transport-Security, Content-Security-Policy.
Database & Performance
26. What is connection pooling and why does it matter?
Creating a new database connection per request is expensive (~100ms). A connection pool keeps N connections open and reuses them. Prisma and other ORMs manage this automatically. Without pooling, high-traffic APIs create thousands of connections and crash the DB.
27. What is an N+1 query problem?
Fetching a list and then making one query per item. 100 posts → 100 separate author queries = 101 total queries. Fix with include (eager loading) or dataloader batching.
28. What is caching and when should you use it in a Node.js API?
Caching stores computed results so repeated requests don't hit the database. Use Redis for: per-user session data, expensive query results, rate limiting counters. Cache when data is read frequently, changes rarely, and eventual consistency is acceptable.
29. What is the difference between horizontal and vertical scaling?
Vertical: bigger server. Horizontal: more servers (Node instances). Node is stateless (no session in memory — use Redis for sessions) which makes horizontal scaling easy. Use a load balancer (Nginx, AWS ALB) in front.
30. How do you detect and fix a memory leak in Node.js?
Use --inspect flag and Chrome DevTools memory profiler. Common causes: forgotten event listeners, growing caches without eviction, closures holding references. Tools: clinic.js, heapdump, node --trace-gc.
Streams & File System
31. What are Node.js streams?
Objects that let you read or write data piece by piece rather than loading it all into memory. Types: Readable, Writable, Duplex (both), Transform (modify data as it passes through). Used for: large file uploads, CSV processing, HTTP responses.
32. What is pipe() used for?
Connects a Readable stream to a Writable stream. Data flows automatically without loading it all in memory:
const readable = fs.createReadStream('large-file.csv');
const writable = fs.createWriteStream('output.csv');
readable.pipe(transform).pipe(writable);33. What is the difference between fs.readFile and fs.createReadStream?
readFile loads the entire file into memory. createReadStream reads in chunks — use it for large files to avoid memory exhaustion.
Advanced
34. What are Worker Threads?
Node.js threads for CPU-intensive work (image processing, encryption, PDF generation). Unlike child_process, they share memory via SharedArrayBuffer. Use the worker_threads module.
35. What is clustering in Node.js?
Creating multiple Node.js processes (one per CPU core) using the cluster module. The master process manages workers; all share the same port. PM2 handles this automatically in production.
36. How do you deploy a Node.js app in production?
Use PM2 as the process manager: pm2 start dist/index.js --instances max --watch. Containerize with Docker. Put Nginx in front for SSL termination and reverse proxying. Set NODE_ENV=production (disables stack traces in error responses, enables production optimizations in Express).
37. What is process.env.NODE_ENV and why does it matter?
A convention for the current environment (development, production, test). Libraries like Express behave differently based on it — e.g., Express doesn't cache views in development. Never expose detailed errors in production.
38. How do you implement rate limiting in Express?
npm install express-rate-limitimport rateLimit from 'express-rate-limit';
app.use('/api/', rateLimit({ windowMs: 60_000, max: 100 }));
app.use('/api/auth/', rateLimit({ windowMs: 60_000, max: 10 }));For distributed systems (multiple Node instances), use a Redis store so limits are shared across instances.
39. What is the purpose of morgan middleware?
HTTP request logger. Logs method, URL, status code, response time. Essential for production observability.
40. What is graceful shutdown?
Handling SIGTERM/SIGINT signals to stop accepting new requests, finish in-flight requests, and close DB connections before exiting. Prevents data loss when containers are redeployed.
process.on('SIGTERM', async () => {
server.close(async () => {
await prisma.$disconnect();
process.exit(0);
});
});Quick Study Guide
Must know cold:
Event loop phases (especially nextTick vs setImmediate)
Why forEach + async is broken
Promise.all vs allSettled
Middleware chain + error handler (4-arg)
req.params vs req.query vs req.body
JWT structure + access/refresh token pattern
bcrypt for passwords (never SHA/MD5)
Connection pooling
N+1 query problem
Horizontal scaling + stateless design
Streams for large files
Graceful shutdownFound this helpful?
Leave a comment
Have a question, correction, or just found this helpful? Leave a note below.