Node.js interview revision notes
Server-side JavaScript: runtime, modules, npm, core APIs, and HTTP. Written for developers preparing for an interview who want to refresh their Node.js fast. Free, no sign-up.
21 topics in these notes
- What is Node.js?
- Modules (CommonJS vs ES modules)
- require() resolution & core modules
- npm & package.json
- __dirname, __filename, global
- File system (fs)
- fs advanced (readdir, stat, watch)
- path, process, Buffer
- HTTP server
- Streams
- Events & EventEmitter
- Environment variables (process.env)
- Async in Node (callbacks, Promises)
- util (promisify, inherits)
- URL & querystring
- Child processes
- OS module
- crypto
- Error handling in Node
- Debugging
- Cluster (multi-core)
What is Node.js?
Simple real-life example (Understand first — very important for understanding)
- Think of the same language that runs when you click buttons on a website.
- Now imagine that language running on a server or on your computer without any browser—just reading files, talking to other services, and handling many requests at once.
- That is what Node does: one language for both the web page and the server.
Real-world idea: one language everywhere. Node lets you use the same language you know from the browser to build servers and tools.
Technical definition
- Node.js is a JavaScript runtime built on Chrome's V8 engine; it runs JS outside the browser.
- Event-driven, non-blocking I/O — uses a single thread + event loop; I/O (files, network) doesn't block the thread.
- Used for: web servers (Express, Fastify), APIs, CLI tools, build tools, real-time apps.
- No
windowordocument; hasglobal,process, and Node-specific APIs (fs,http, etc.).
Simple practical example
Event-driven, non-blocking I/O — uses a single thread + event loop; I/O (files, network) doesn't block the thread.
Code example
// Run with: node script.js
console.log("Hello from Node!");
console.log("Current dir:", process.cwd());
console.log("Node version:", process.version);Why it matters
Backend and tooling jobs often use Node. Understanding runtime vs browser and non-blocking I/O is a common interview topic.
Interview tip
Say: "Node is a JS runtime on V8; event-driven, non-blocking I/O; used for servers and tools. No DOM; has process, fs, http."
Modules (CommonJS vs ES modules)
Simple real-life example (Understand first — very important for understanding)
- Like a recipe book: you don't copy the whole book into your kitchen; you open the page you need.
- In code, you "pull in" only the parts you need from other files instead of writing everything in one huge file.
- There are two main ways to do this (like two styles of recipe books); each project usually picks one and sticks to it.
Real-world idea: reuse and organize. Modules let you split code into small, reusable pieces and load only what you need.
Technical definition
- CommonJS:
const x = require('module'); export withmodule.exports = ...orexports.key = .... - ES modules (ESM):
import x from 'module'; export withexport default ...orexport { a, b }. - Node uses CommonJS by default; ESM when file has
.mjsor"type": "module"inpackage.json. - Don't mix require and import in the same file; stick to one system per project (or per file in ESM).
Simple practical example
ES modules (ESM): import x from 'module'; export with export default .
Code example
// CommonJS: utils.js
module.exports = { add: (a, b) => a + b };
// or: exports.add = (a, b) => a + b;
// app.js
const { add } = require('./utils');
console.log(add(2, 3)); // 5Why it matters
Most Node codebases use CommonJS; modern ones often use ESM. Interviewers ask "difference between require and import" or "how do you export in Node?"
Interview tip
"CommonJS: require/module.exports, synchronous load. ESM: import/export, async load, use .mjs or type:module. Don't mix in one file."
require() resolution & core modules
Simple real-life example (Understand first — very important for understanding)
- When you ask for "salt," you might mean the one in your kitchen, or from the shop, or from a friend's kitchen.
- The system has rules: first check the built-in cupboard, then the shop down the road, then the exact path you give.
- Node does the same when you ask for a module: it looks in built-in stuff first, then in installed packages, then in files you point to.
Real-world idea: knowing where things come from. Understanding this order avoids "can't find it" errors and keeps your project tidy.
Technical definition
require('name')resolves: core module (e.g.fs,path) →node_modules→ path (relative/absolute).- Core modules:
fs,path,http,events,util,os,crypto,child_process,url,querystring, etc. - Relative:
require('./utils')(same dir),require('../lib'); omit.jsfor same-name file. - Package:
require('lodash')looks innode_modules; resolution walks up directories.
Simple practical example
Core modules: fs, path, http, events, util, os, crypto, child_process, url, querystring, etc.
Code example
const fs = require('fs'); // core
const path = require('path'); // core
const myUtil = require('./utils'); // relative
const pkg = require('express'); // node_modulesWhy it matters
Understanding where Node looks for modules avoids "Cannot find module" and helps with project structure and monorepos.
Interview tip
"Resolution order: core → node_modules (walking up) → file path. Relative paths use ./ or ../."
npm & package.json
Simple real-life example (Understand first — very important for understanding)
- Like an app store for code: you say what your project needs, and a tool downloads and installs those pieces.
- A single file lists your project's name, version, and what it depends on—like a shopping list for your app.
- You can also define short commands (e.g. "start" or "test") so everyone runs the same steps the same way.
Real-world idea: one place to list what you need and how to run the project. Every Node project uses this.
Technical definition
- npm = Node Package Manager; installs dependencies and runs scripts.
npm initcreatespackage.json(name, version, scripts, dependencies).npm install <pkg>adds todependencies;npm install -D <pkg>adds todevDependencies.- Scripts:
"start": "node index.js","test": "jest"— run withnpm run start/npm test. node_modulesholds installed packages; usually not committed;package-lock.jsonlocks versions.
Simple practical example
npm init creates package.
Code example
// package.json (minimal)
{
"name": "my-api",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "node --watch index.js"
},
"dependencies": { "express": "^4.18.0" }
}Why it matters
Every Node project uses package.json and npm (or yarn/pnpm). Knowing dependencies vs devDependencies and how to run scripts is basic expectation.
Interview tip
"npm install adds packages; package.json has scripts and dependencies. Use -D for dev-only tools. package-lock.json locks versions for reproducible installs."
__dirname, __filename, global
Simple real-life example (Understand first — very important for understanding)
- Imagine you are in a building: "Which room am I in?" and "What is the full address of this room?"
- In a script, the program often needs to know "which folder is this file in?" and "what is the full path of this file?"
- Those two answers are like your current location so the script can find other files next to it.
Real-world idea: knowing where you are. Scripts use this to load configs or other files in the same folder without breaking when you move the project.
Technical definition
__dirname: absolute path of the directory containing the current file (not in ESM; useimport.meta.url).__filename: absolute path of the current file.global: global object in Node (likewindowin browser); avoid attaching globals.- Use
path.join(__dirname, 'file.json')to resolve paths relative to current script.
Simple practical example
__filename: absolute path of the current file.
Code example
const path = require('path');
const configPath = path.join(__dirname, 'config.json');
console.log('Script dir:', __dirname);
console.log('Script file:', __filename);Why it matters
Loading config or assets relative to the script file is common; __dirname is the standard way in CommonJS.
Interview tip
"__dirname is current file's directory, __filename is full path. Use with path.join for relative paths. In ESM use import.meta.url."
File system (fs)
Simple real-life example (Understand first — very important for understanding)
- Like reading and writing papers in a filing cabinet: open a drawer, read a file, or put a new one in.
- You can do it in two ways: wait until the read is done (like standing at the cabinet), or do something else and get a signal when it's ready.
- The second way keeps the program responsive when dealing with many files or slow disks.
Real-world idea: files are how programs store and load data. Node gives you simple ways to read and write files, with options for waiting or not.
Technical definition
fsmodule: read/write files and directories; sync versions (e.g.readFileSync) and async callback versions (e.g.readFile).- Prefer
fs.promises(e.g.fs.promises.readFile) orfs/promisesfor Promise-based API; use with async/await. - Common methods:
readFile,writeFile,readdir,mkdir,exists(oraccess),stat. - Paths: use
path.joinorpath.resolvefor cross-platform paths; avoid hardcoding/or\.
Simple practical example
Prefer fs.
Code example
const fs = require('fs').promises;
const path = require('path');
async function readConfig() {
const filePath = path.join(process.cwd(), 'config.json');
const data = await fs.readFile(filePath, 'utf-8');
return JSON.parse(data);
}Why it matters
File I/O is central to scripts, config loading, and logging. Interview questions: "How do you read a file in Node?" or "sync vs async fs?"
Interview tip
"Use fs.promises or fs/promises with async/await. readFile/writeFile for files; readdir for directories. Use path.join for paths."
fs advanced (readdir, stat, watch)
Simple real-life example (Understand first — very important for understanding)
- Like listing what is inside a folder on your computer: names of files and subfolders, and whether something is a file or a folder.
- You can also ask "how big is this file?" or "when was it last changed?" without opening it.
- Some tools can even tell you when a file or folder changes, like a watchman at the door.
Real-world idea: inspecting and watching. Beyond read/write, you can list directories, get file info, and react to changes.
Technical definition
fs.readdir(path)/fs.promises.readdir: list directory contents (optionally withwithFileTypes: true).fs.stat(path): metadata (isFile(), isDirectory(), size, mtime); use for existence and type checks.fs.mkdir(path, { recursive: true }): create directory (recursive creates parents).fs.watch(path): watch file/dir for changes (platform-dependent; consider chokidar for production).
Simple practical example
fs.
Code example
const fs = require('fs').promises;
const path = require('path');
async function listDir(dirPath) {
const entries = await fs.readdir(dirPath, { withFileTypes: true });
for (const e of entries) {
const stat = await fs.stat(path.join(dirPath, e.name));
console.log(e.name, stat.isFile() ? 'file' : 'dir', stat.size);
}
}Why it matters
Listing dirs, checking file type/size, and creating nested dirs are common in scripts and build tools.
Interview tip
"readdir for listing, stat for metadata (isFile, size), mkdir with recursive: true. watch for file changes (use libs for reliability)."
path, process, Buffer
Simple real-life example (Understand first — very important for understanding)
- Paths are like addresses: "same building" vs "one floor up" vs "another city." A path helper joins and normalizes these so they work on any computer.
- Process is like the "control room" of your running program: environment, current directory, command-line arguments.
- Buffer is like a temporary tray for raw data (e.g. file bytes or network chunks) before you turn it into text or numbers.
Real-world idea: paths, control room, and raw data. These three help you work with files, system info, and binary data safely.
Technical definition
- path:
path.join('a', 'b', 'c'),path.resolve('..', 'file.js'),path.basename,path.extname,path.dirname. - process:
process.cwd(),process.argv,process.env,process.exit(code),process.version. - Buffer: fixed-size raw binary data;
Buffer.from('hello'),Buffer.alloc(10); use when dealing with binary or encoding (e.g. streams, crypto).
Simple practical example
process: process.
Code example
const path = require('path');
const fullPath = '/home/user/project/src/index.js';
console.log(path.basename(fullPath)); // index.js
console.log(path.dirname(fullPath)); // /home/user/project/src
console.log(path.extname(fullPath)); // .js
// CLI args: node script.js arg1 arg2
console.log(process.argv.slice(2)); // ['arg1', 'arg2']Why it matters
path and process are used in almost every Node app. Buffer comes up when discussing streams, file encoding, or binary data.
Interview tip
"path for join/resolve/basename/dirname. process for cwd, argv, env, exit. Buffer for binary data; Buffer.from string or Buffer.alloc size."
HTTP server
Simple real-life example (Understand first — very important for understanding)
- Imagine a receptionist: people come to the door with requests; the receptionist routes each to the right desk and sends back a reply.
- A server program listens at a "door" (port), accepts requests, and sends back responses—like handing out forms and collecting filled ones.
- You can serve web pages, send JSON for an API, or stream data in real time.
Real-world idea: a program that waits for requests and answers them. Node makes it easy to build this receptionist so you can create web servers and APIs.
Technical definition
- Built-in
httpmodule:http.createServer((req, res) => { ... }); callserver.listen(port). req:url,method,headers; body must be read (e.g. in chunks or with a helper).res:setHeader,writeHead(status),write,end; always callres.end()to finish the response.- In practice we often use Express/Fastify on top of http for routing and middleware.
Simple practical example
req: url, method, headers; body must be read (e.
Code example
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from Node server!\n');
});
server.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});Why it matters
Creating a minimal HTTP server is a classic Node interview question. It shows you understand request/response and the event-driven model.
Interview tip
"http.createServer gets (req, res). Set status and headers, then res.end(). req has method, url, headers; body is streamed. Express wraps this with routing and middleware."
Streams
Simple real-life example (Understand first — very important for understanding)
- Like a water pipe: you don't need to collect the whole river in a bucket; water flows through, and you process it as it passes.
- For data: instead of loading a huge file into memory, you read it in chunks and handle each chunk—so big files or live data don't overwhelm the program.
- Pipes connect one stream to another, so data flows from source to destination without you holding everything in the middle.
Real-world idea: process data as it flows. Streams let you handle large files and live data without loading everything at once.
Technical definition
- Streams: abstract interface for reading/writing data in chunks (memory-efficient for large data).
- Types: Readable, Writable, Duplex, Transform. Events:
data,end,error,finish. readable.pipe(writable): pipe a Readable into a Writable (e.g. file → response).- fs.createReadStream, fs.createWriteStream; http req/res are streams.
Simple practical example
Types: Readable, Writable, Duplex, Transform.
Code example
const fs = require('fs');
const path = require('path');
// Stream a file to response
const filePath = path.join(__dirname, 'large.json');
const readStream = fs.createReadStream(filePath);
readStream.pipe(res); // res is http.ServerResponseWhy it matters
Serving large files, logs, or processing data in chunks uses streams; pipe() is a common interview topic.
Interview tip
"Streams process data in chunks. Readable/Writable; pipe() connects them. createReadStream/createWriteStream for files; req/res are streams."
Events & EventEmitter
Simple real-life example (Understand first — very important for understanding)
- Like a doorbell: something happens (someone presses it), and whoever is listening (you) reacts (you open the door).
- In code, one part says "when X happens, do Y" without the two parts needing to know each other's details.
- Many things in Node work this way: "when data arrives," "when the connection closes," "when a file is read."
Real-world idea: react when something happens. Events and emitters let different parts of your program respond to actions without being tightly glued together.
Technical definition
- Node uses event-driven model; many APIs extend
EventEmitter(e.g. streams, http). emitter.on('event', handler),emitter.emit('event', ...args),emitter.once,emitter.off.- Create:
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {}. - Default max listeners is 10; increase with
emitter.setMaxListeners(n)if needed (avoid memory leaks).
Simple practical example
emitter.
Code example
const EventEmitter = require('events');
class Logger extends EventEmitter {}
const log = new Logger();
log.on('message', (msg) => console.log('Log:', msg));
log.emit('message', 'Hello'); // Log: HelloWhy it matters
Understanding EventEmitter explains how Node APIs (http, streams) work and how to build event-based code.
Interview tip
"EventEmitter: on, emit, once, off. Many Node APIs inherit it. Extend EventEmitter for custom event-based objects."
Environment variables (process.env)
Simple real-life example (Understand first — very important for understanding)
- Like a notice board at the entrance: "today's special," "which branch is this," "is the kitchen in debug mode?"
- Environment variables are settings that can change per machine or environment without changing the code.
- You use them for secrets (don't put passwords in code), for switching between dev and production, and for things that differ per deployment.
Real-world idea: config that lives outside the code. Env vars keep secrets and environment-specific settings in one place.
Technical definition
- Environment variables are available as
process.env.KEY(e.g.process.env.NODE_ENV,process.env.PORT). - Set in shell:
PORT=3000 node app.js(Unix); or use a.envfile with a package likedotenv(load before reading env). - Use for: config (DB URL, API keys), environment (development/production), port; never commit secrets to code.
Simple practical example
Set in shell: PORT=3000 node app.
Code example
const port = process.env.PORT || 3000;
const isDev = process.env.NODE_ENV !== 'production';
// Load .env with: require('dotenv').config();
// Then: process.env.DATABASE_URLWhy it matters
Config and secrets are typically passed via env. Interviewers expect you to know how to read them and that you don't hardcode secrets.
Interview tip
"Config and secrets via process.env. Use dotenv for .env in development. Never commit .env or hardcode secrets."
Async in Node (callbacks, Promises)
Simple real-life example (Understand first — very important for understanding)
- Like ordering food: you place the order, do something else (chat, read), and when the food is ready you get a signal and eat.
- You don't stand at the counter blocking everyone until your order is done; the kitchen works in parallel.
- In Node, I/O (files, network, database) works like that: start the operation, do other work, and react when it finishes.
Real-world idea: don't wait idle. Async lets the program do other work while waiting for slow tasks, so one thread can handle many operations.
Technical definition
- Many Node APIs are callback-based:
fs.readFile('file.txt', (err, data) => { ... }); convention: first arg is error. - Promise-based:
fs.promises.readFile, or wrap callbacks withutil.promisify. - Use async/await with Promise-based APIs to avoid callback hell; handle errors with try/catch.
- Node is single-threaded; long CPU work can block the event loop; use worker threads or split work for heavy computation.
Simple practical example
Promise-based: fs.
Code example
const fs = require('fs').promises;
async function readTwoFiles() {
try {
const [a, b] = await Promise.all([
fs.readFile('a.txt', 'utf-8'),
fs.readFile('b.txt', 'utf-8')
]);
return { a, b };
} catch (err) {
console.error(err);
throw err;
}
}Why it matters
Node code is async by default. Interviewers ask about callbacks vs Promises, error handling, and sometimes event loop / blocking.
Interview tip
"Node uses callbacks by default; use fs.promises or promisify for Promises. Prefer async/await and try/catch. Promise.all for parallel I/O."
util (promisify, inherits)
Simple real-life example (Understand first — very important for understanding)
- Like a kitchen drawer of small tools: a timer, a way to turn one type of thing into another, or to check "is this actually a number?"
- Utility helpers don't do the main cooking but make everyday tasks easier and your code cleaner.
- Examples: format strings, inspect objects for debugging, or wrap old-style callbacks into a modern style.
Real-world idea: small helpers that simplify common jobs. Util gives you timers, type checks, and formatting so you don't reinvent them.
Technical definition
util.promisify(fn): turns callback-based function (err, result) into one returning a Promise.util.inherits(Child, Parent): set up prototype chain (old style; prefer class extends).util.format: sprintf-style formatting;util.types: type checks (isPromise, isArrayBuffer, etc.).
Simple practical example
util.
Code example
const util = require('util');
const fs = require('fs');
const readFilePromise = util.promisify(fs.readFile);
async function read() {
const data = await readFilePromise('config.json', 'utf-8');
return JSON.parse(data);
}Why it matters
promisify is the standard way to use callback APIs with async/await without wrapping by hand.
Interview tip
"util.promisify converts (err, result) callbacks to Promises. util.inherits for old-style inheritance; prefer class."
URL & querystring
Simple real-life example (Understand first — very important for understanding)
- A web address is like a full sentence: "Which place? Which page? And what extra options (like size or color)?"
- Parsing means breaking that sentence into parts: path, query parameters, and sometimes fragments.
- You use this when handling links, API calls, or form data that comes as a string.
Real-world idea: addresses have structure. URL and querystring tools help you read and build addresses and their parameters correctly.
Technical definition
url.parse/new URL(input): parse URL into protocol, host, pathname, search, hash.URLSearchParams: get/set query params;new URLSearchParams(searchString)orurl.searchParams.querystringmodule:querystring.parse('a=1&b=2'),querystring.stringify(obj)(legacy; URLSearchParams preferred).
Simple practical example
URLSearchParams: get/set query params; new URLSearchParams(searchString) or url.
Code example
const { URL } = require('url');
const u = new URL('https://api.com/list?page=2&limit=10');
console.log(u.pathname); // /list
console.log(u.searchParams.get('page')); // 2
u.searchParams.set('sort', 'name');Why it matters
Parsing request URLs and query strings is standard in HTTP servers and APIs.
Interview tip
"Use URL and URLSearchParams for parsing URLs and query strings. querystring exists but URLSearchParams is modern."
Child processes
Simple real-life example (Understand first — very important for understanding)
- Like asking someone else to run an errand: you give them a task, they do it (maybe in another room or building), and they come back with a result or a message.
- Your program can start another program (e.g. a script, a command-line tool) and wait for it or listen to its output.
- Use this when you need to run system commands, other scripts, or heavy work in a separate process.
Real-world idea: delegate work to another process. Child processes let Node run external programs and use their output or result.
Technical definition
child_process.exec: run shell command, buffer output;execSyncfor sync.child_process.spawn: run command with streaming stdout/stderr; better for long-running or large output.child_process.fork: spawn Node process that can communicate via IPC (send/on('message')).- Use
execfor short commands;spawnfor scripts or when you need streams.
Simple practical example
child_process.
Code example
const { exec } = require('child_process');
exec('ls -la', (err, stdout, stderr) => {
if (err) { console.error(err); return; }
console.log(stdout);
});
// With promises
const { promisify } = require('util');
const execPromise = promisify(exec);Why it matters
Running CLI tools, scripts, or other programs from Node is common in build tools and DevOps.
Interview tip
"exec for simple shell commands (buffered); spawn for streaming or long-running; fork for Node subprocess with IPC."
OS module
Simple real-life example (Understand first — very important for understanding)
- Like asking the building manager: "How much memory is there? How many CPUs? What OS is this? What is the temp directory?"
- The OS module gives your script a way to ask the system for this information so you can adapt (e.g. use more workers on a big machine).
- Useful for tuning, logging, or choosing paths that work on the current machine.
Real-world idea: ask the system about the machine. OS helpers let your program adapt to the environment it runs on.
Technical definition
os.platform(),os.arch(),os.cpus(),os.totalmem(),os.freemem().os.homedir(),os.tmpdir(),os.hostname(),os.EOL(line ending).- Use for: platform checks, reporting system info, temp file paths, concurrency based on CPU count.
Simple practical example
os.
Code example
const os = require('os');
console.log('Platform:', os.platform());
console.log('CPUs:', os.cpus().length);
console.log('Free memory (MB):', Math.round(os.freemem() / 1024 / 1024));
console.log('Temp dir:', os.tmpdir());Why it matters
CLI and monitoring tools often need platform, memory, or CPU info; tmpdir and EOL for cross-platform scripts.
Interview tip
"os for platform, cpus, memory, homedir, tmpdir. Useful for cross-platform paths and system info."
crypto
Simple real-life example (Understand first — very important for understanding)
- Like a safe: you can create a fingerprint of some data (hash), or lock a message so only someone with the right key can read it (encrypt).
- Hashing is one-way: same input always gives the same fingerprint, but you can't get the original back from the fingerprint.
- Encryption is two-way: with the key you can lock and unlock; used for passwords (store hashes) and for secure communication.
Real-world idea: protect and identify data. Crypto gives you hashing (e.g. for passwords) and encryption (e.g. for secrets).
Technical definition
crypto.createHash('sha256'): hashing;hash.update(data).digest('hex').crypto.randomBytes(n): secure random bytes (for tokens, IDs); usetoString('hex')for string.- Also: HMAC, encryption (createCipheriv/createDecipheriv), pbkdf2 for password hashing (with salt).
Simple practical example
crypto.
Code example
const crypto = require('crypto');
const hash = crypto.createHash('sha256').update('hello').digest('hex');
const token = crypto.randomBytes(32).toString('hex');
console.log('Hash:', hash);
console.log('Token:', token);Why it matters
Hashing, tokens, and password handling are common in auth and APIs; crypto is the built-in option.
Interview tip
"crypto for hashing (createHash), randomBytes for tokens, HMAC/encryption for auth. Use salt and proper algo for passwords (e.g. pbkdf2)."
Error handling in Node
Simple real-life example (Understand first — very important for understanding)
- When something goes wrong—a file missing, network down—the program shouldn't just crash; it should catch the problem and respond (e.g. show a message or retry).
- Errors can be "expected" (e.g. user typed wrong input) or unexpected (e.g. disk full); you handle both so the app stays stable.
- In Node, you use try/catch for sync code and catch on promises or error callbacks for async code.
Real-world idea: plan for things to go wrong. Good error handling keeps the app running and gives clear feedback instead of crashing.
Technical definition
- Callback convention: first argument is
err; if truthy, handle error and return (or pass up). - Promises: use try/catch with async/await, or
.catch()on promises; always handle rejections to avoid unhandledRejection. - In HTTP servers: set 500 status, send error message (avoid leaking stack in production); log full error server-side.
process.on('uncaughtException', fn)/unhandledRejection: last resort; log and exit gracefully.
Simple practical example
Promises: use try/catch with async/await, or .
Code example
// Error-first callback
fs.readFile('missing.txt', (err, data) => {
if (err) {
console.error('Read failed:', err.message);
return;
}
console.log(data);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled rejection at', promise, reason);
});Why it matters
Node apps must handle async errors explicitly; unhandled rejections can crash the process. Interviewers ask about error-first callbacks and global handlers.
Interview tip
"Callbacks: first arg is err. Promises: try/catch or .catch. Handle unhandledRejection; in HTTP send 500 and log."
Debugging
Simple real-life example (Understand first — very important for understanding)
- Like putting a mirror where you can't see: you add logs or breakpoints to see what the program is doing at each step.
- You inspect variables, follow the flow, and see where the behavior differs from what you expect.
- Node and tools like the built-in debugger or VS Code let you pause, step, and inspect so you can find and fix bugs.
Real-world idea: see inside the running program. Debugging tools and logs help you find why something doesn't work as expected.
Technical definition
node --inspect script.js: start with inspector; openchrome://inspectin Chrome to attach.node --inspect-brk: break on first line (useful for stepping from start).console.log,console.error,console.table,console.time/timeEnd.- VS Code: launch config with "type": "node" and "request": "launch"; set breakpoints in editor.
Simple practical example
node --inspect-brk: break on first line (useful for stepping from start).
Code example
console.time('fetch');
await fetchData();
console.timeEnd('fetch'); // fetch: 123ms
console.table([{ a: 1, b: 2 }, { a: 3, b: 4 }]);Why it matters
Knowing how to attach a debugger and use console effectively speeds up development and is expected in professional setups.
Interview tip
"Use --inspect and Chrome DevTools or VS Code debugger. console.time/timeEnd for quick perf; console.table for arrays of objects."
Cluster (multi-core)
Simple real-life example (Understand first — very important for understanding)
- Like having several receptionists at the same company: one can take a call while another handles a different customer.
- Cluster lets you run multiple copies of your Node process so they share the work and use more than one CPU.
- If one copy crashes, the others keep serving; the master can restart the one that failed.
Real-world idea: use more than one worker. Cluster helps you use all CPU cores and keep the server running even if one worker fails.
Technical definition
clustermodule lets you run multiple Node processes (workers) that share the same port. Master forks workers; workers do the work (e.g. HTTP server).cluster.isPrimary— am I the master?cluster.fork()— spawn worker. Workers run the same script; usecluster.isWorkerto run server in workers. Listen on same port; OS distributes connections.- Use: utilize all CPU cores for a single Node app. Restart workers on crash;
cluster.on('exit', (worker) => cluster.fork()). PM2 can also do cluster mode.
Simple practical example
cluster.
Code example
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
if (cluster.isPrimary) {
for (let i = 0; i < numCPUs; i++) cluster.fork();
cluster.on('exit', (worker) => cluster.fork());
} else {
require('http').createServer((req, res) => res.end('ok')).listen(3000);
}Why it matters
Node is single-threaded; one process uses one core. "How do you use all CPU cores?" — cluster or PM2 cluster mode. Common interview topic.
Interview tip
"cluster module: primary forks workers; workers run server on same port. Use all cores; restart worker on exit. PM2 cluster mode is an alternative."
Practise the questions
Read the top 50 Node.js interview questions and answers to test yourself after revising.
More Backend & APIs notes
Express · REST API · JWT · Google Cloud (GCP) · All developer notes