Interview Questions
A focused set of Node.js interview questions with concise, senior-level answers. They’re grouped by topic so you can drill into weak areas. Each answer is deliberately short—enough to demonstrate understanding without rambling.
Fundamentals
What is Node.js and what is it not? Node.js is a JavaScript runtime built on V8 that runs JavaScript outside the browser. It is not a language and not a framework—it’s the environment that executes your code, bundling V8 plus native libraries for file, network, and OS access.
What is V8? Google’s open-source JavaScript engine, the same one in Chrome. It compiles JavaScript to optimized machine code, giving Node its execution speed.
What is libuv? A C library that provides Node’s event loop, thread pool, and cross-platform asynchronous I/O. It handles the slow operations off the main thread.
Is Node.js single-threaded? Your JavaScript runs on a single thread, but libuv maintains a thread pool (default 4) for certain operations like file I/O and crypto. So the model is single-threaded JS with multi-threaded I/O underneath.
Why is Node good for I/O-heavy apps but weak for CPU-bound work? Non-blocking I/O lets one thread juggle thousands of connections while waiting. But a heavy computation occupies that single thread and blocks everything else. CPU work needs Worker Threads or a separate service.
What is the difference between global and globalThis?
global is Node’s global object; globalThis is the standardized cross-platform reference that works in both Node and browsers.
Event Loop & Async
Name the phases of the event loop.
Timers, pending callbacks, poll, check, and close. Microtasks (process.nextTick and Promises) drain between each phase.
What’s the difference between setImmediate and setTimeout(fn, 0)?
setImmediate runs in the check phase; setTimeout(fn, 0) runs in the timers phase. Inside an I/O callback, setImmediate always fires first. At the top level the order isn’t guaranteed.
What does process.nextTick do, and what’s the risk?
It queues a callback to run after the current operation, before the event loop continues and before Promise microtasks. The risk: recursively scheduling nextTick starves the loop and blocks all I/O.
Macrotask vs microtask?
Macrotasks are loop-phase callbacks (timers, I/O, setImmediate). Microtasks (nextTick, Promises) drain completely between macrotasks, giving them higher effective priority.
What is callback hell and how do you avoid it? Deeply nested callbacks that scatter error handling and hurt readability. Avoid it with Promises and async/await, which flatten control flow.
How do you run async operations concurrently?
Start them without awaiting, then combine: Promise.all (fail-fast), Promise.allSettled (all results), Promise.race/Promise.any (first to settle/fulfill).
Why might await inside forEach not work?
forEach ignores the returned Promise, so it doesn’t wait. Use for...of for sequential awaits or Promise.all(map(...)) for parallel.
Modules
CommonJS vs ESM?
CommonJS uses require/module.exports and loads synchronously; ESM uses import/export, loads asynchronously, and supports top-level await. Enable ESM with .mjs or "type": "module".
What is package-lock.json for?
It pins the exact resolved versions of your entire dependency tree, ensuring reproducible installs across machines and CI.
dependencies vs devDependencies?
dependencies are needed at runtime in production; devDependencies are only for development (linters, test runners, bundlers) and can be omitted in production installs.
Explain semantic versioning and the ^ vs ~ ranges.
Versions are MAJOR.MINOR.PATCH. ^1.2.3 allows minor and patch updates (<2.0.0); ~1.2.3 allows only patch updates (<1.3.0).
Is require cached?
Yes. After first load, a module is cached and subsequent require calls return the same instance—useful for singletons.
Express / HTTP
What is middleware in Express?
A function (req, res, next) that runs in sequence on matching requests. It can modify req/res, end the response, or call next() to continue. Auth, logging, and parsing are all middleware.
How does Express recognize error-handling middleware?
By its arity: error handlers take four arguments (err, req, res, next). Register them last so they catch errors from earlier routes.
How do you read route params, query, and body?
req.params for :id segments, req.query for the query string, and req.body for the parsed payload (after express.json()).
Which status codes should a REST API use?
200 OK, 201 Created, 204 No Content (delete), 400 Bad Request, 401/403 auth, 404 Not Found, 500 Server Error.
Performance & Errors
How do you handle CPU-intensive work without blocking?
Move it to Worker Threads, the cluster module, or a separate microservice so the main event loop stays responsive.
What is the cluster module?
It forks multiple Node processes that share a server port, letting you use all CPU cores. Each worker has its own event loop and memory.
How do you handle uncaught exceptions and unhandled rejections?
Listen on process.on("uncaughtException") and process.on("unhandledRejection") for logging and graceful shutdown—but treat them as last-resort safety nets, not primary error handling. Always handle errors locally with try/catch or .catch.
How do you avoid blocking the event loop?
Prefer async APIs over their Sync variants, keep loops short, stream large data instead of buffering, and offload heavy computation to workers.
What causes a memory leak in Node and how do you find one?
Common causes: unbounded caches, lingering event listeners, and closures holding references. Diagnose with heap snapshots in Chrome DevTools or --inspect, and watch RSS over time.