Interview Q&A / Node.js
Node.js interview questions
The event loop on the server, streams, modules and building APIs with Express.
Prefer rapid revision? Practise Node.js short interview answers →
- If Node.js is single-threaded, how does it handle thousands of requests at the same time?
Your JavaScript runs on one main thread, but slow work like network and file I/O is handed to the operating system or libuv's thread pool. The main thread never sits waiting; it keeps taking new requests and runs each callback when its I/O finishes.
BeginnerIn-depth3 min read - What is middleware in Express.js and how does next() work?
Middleware is a function that runs between the request arriving and the response being sent. It receives req, res and next, and it either ends the response or calls next() to pass control to the next middleware or route. Calling next(err) jumps to error-handling middleware.
BeginnerIn-depth2 min read - What is the difference between CommonJS (require) and ES modules (import) in Node.js?
CommonJS uses require and module.exports, loads files synchronously, and was Node's original system. ES modules use import and export, are the JavaScript standard, are analysed before running, and support top-level await. Node supports both.
BeginnerIn-depth3 min read - What is the difference between dependencies and devDependencies, and why do we need package-lock.json?
dependencies are packages your app needs to run in production; devDependencies are only needed while developing, testing or building. package-lock.json records the exact version of every installed package so every machine and deployment gets the same dependency tree.
BeginnerIn-depth3 min read - How do you handle errors in asynchronous Node.js code, and what is an unhandled promise rejection?
Use try/catch around await, .catch() on promise chains, and the error-first argument in callbacks. An unhandled rejection is a promise that fails with no handler attached; since Node 15 it crashes the process by default, so every promise needs a catch somewhere.
IntermediateIn-depth3 min read - What are streams in Node.js and why would you use them for large files?
A stream processes data in small chunks as it arrives instead of loading everything into memory at once. For a large file, streams keep memory use low and let you start sending data immediately, and pipeline() handles backpressure and errors for you.
IntermediateIn-depth3 min read - What is the difference between process.nextTick, setImmediate and setTimeout in Node.js?
process.nextTick runs right after the current operation, before promise callbacks and before the event loop moves on. setImmediate runs in the check phase, right after I/O polling. setTimeout(fn, 0) runs in the timers phase after at least about 1 ms.
IntermediateIn-depth3 min read - When would you use worker_threads, cluster or child_process in Node.js?
Use worker_threads for CPU-heavy JavaScript inside one process, cluster to run several copies of a server across CPU cores sharing one port, and child_process to run a separate program or script such as ffmpeg or a Python file.
AdvancedIn-depth3 min read - How do you check whether a file exists in Node.js?
Use fs.promises.access in a try/catch, or fs.existsSync for quick sync checks. Better still, skip the check and handle the ENOENT error when you open the file, because the file can change between check and use.
BeginnerQuick answer1 min read - How do you convert a string to base64 and back in Node.js?
Use Buffer.from(text, "utf8").toString("base64") to encode and Buffer.from(b64, "base64").toString("utf8") to decode. Base64 is an encoding for transport, not encryption.
BeginnerQuick answer1 min read - How do you create a basic HTTP server in Node.js without Express?
Use the built-in http module: http.createServer takes a handler with request and response objects, and listen starts it on a port. You set status and headers on the response and finish it with end.
BeginnerQuick answer1 min read - How do you get __dirname and __filename inside an ES module?
They do not exist in ES modules. Use import.meta.url with fileURLToPath and path.dirname, or on recent Node versions import.meta.dirname and import.meta.filename.
BeginnerQuick answer1 min read - How do you list all files in a folder and its subfolders in Node.js?
Use fs.promises.readdir with the recursive option on recent Node versions, or write a small recursive function using withFileTypes to tell files from directories.
BeginnerQuick answer1 min read - How do you tell Node.js to treat your files as ES modules?
Set "type": "module" in package.json so .js files are ESM, or use the .mjs extension for individual files. Use .cjs to force CommonJS inside an ESM project.
BeginnerQuick answer1 min read - What are the four types of streams in Node.js?
Readable (data source, like a file read), Writable (destination, like a file write or HTTP response), Duplex (both, like a TCP socket), and Transform (a duplex that changes data as it passes, like gzip).
BeginnerQuick answer1 min read - What does util.promisify do and when is it useful?
It converts a function that takes an error-first callback as its last argument into one that returns a promise, so older callback APIs can be used with async/await.
BeginnerQuick answer1 min read - What happens when you require the same module twice in Node.js?
The file runs only once. Node caches the exported object in require.cache, so later require calls return the same object, which means shared state between files.
BeginnerQuick answer1 min read - What happens when you run a heavy CPU loop inside a Node.js request handler?
The single JavaScript thread is busy, so the event loop cannot serve any other request until the loop ends. Every user sees delays. Move heavy work to worker threads, a queue, or break it into chunks.
BeginnerQuick answer1 min read - What is a Buffer in Node.js and why does it exist?
A Buffer is a fixed-size chunk of raw memory holding bytes. Node uses it for binary data such as files, network packets and images, because JavaScript strings are meant for text, not raw bytes.
BeginnerQuick answer1 min read - What is callback hell and how do you avoid it?
Callback hell is deeply nested callbacks where each step lives inside the previous one, making code hard to read and handle errors in. Avoid it with named functions, promises, and async/await.
BeginnerQuick answer1 min read - What is the difference between fs.readFileSync, fs.readFile and fs.promises.readFile?
readFileSync blocks the thread until done. readFile takes a callback and does not block. fs.promises.readFile returns a promise for use with await. In servers, prefer the non-blocking forms.
BeginnerQuick answer1 min read - What is the difference between module.exports and exports in CommonJS?
exports is just a shortcut variable pointing at module.exports. You can add properties to either, but only module.exports is what require returns, so reassigning exports alone exports nothing.
BeginnerQuick answer1 min read - What is the difference between path.join and path.resolve?
join just glues segments together with the correct separator. resolve builds an absolute path, processing segments right to left until it has one, and falls back to the current working directory.
BeginnerQuick answer1 min read - What is the difference between Promise.all and Promise.allSettled?
Promise.all rejects as soon as any promise rejects and gives you results only if all succeed. Promise.allSettled always waits for every promise and reports each outcome as fulfilled or rejected.
BeginnerQuick answer1 min read - Why use path.join instead of joining file paths with plus signs?
path.join uses the correct separator for the operating system, normalises extra slashes and dot segments, and avoids missing or doubled slashes, so paths work on Windows, Linux and macOS.
BeginnerQuick answer1 min read - How can CommonJS code load an ES module?
Use dynamic import(), which works in CommonJS and returns a promise. Plain require of an ES module was not allowed historically; newer Node versions added limited support, so dynamic import is the safe choice.
IntermediateQuick answer1 min read - How do you read a very large file line by line in Node.js?
Create a read stream and pass it to readline.createInterface, then loop with for await. Only a small chunk sits in memory at a time, unlike readFile, which loads the whole file.
IntermediateQuick answer1 min read - How do you send a large file to the browser without loading it all in memory?
Create a read stream of the file and pipe it into the HTTP response. Set the Content-Type and, if known, Content-Length headers first, and handle stream errors before any bytes are sent.
IntermediateQuick answer1 min read - How do you write a JSON file in Node.js without risking a half-written file?
Write the data to a temporary file in the same folder, then rename it over the target. Rename is atomic on the same filesystem, so readers see either the old file or the complete new one.
IntermediateQuick answer1 min read - Predict the output: setTimeout, a promise, process.nextTick and plain logs together
Synchronous code runs first, then process.nextTick callbacks, then promise callbacks (microtasks), then timers. So the order is sync, nextTick, promise, setTimeout.
IntermediateQuick answer1 min read