Node.js45 min read

Node.js Interview Questions: 50 Essential Questions for Developers

Comprehensive collection of 50 essential Node.js interview questions covering event loop, async programming, modules, streams, and backend concepts. Free Node.js, NodeJS, Node JS interview questions with answers. Node.js interview prep guide.

Sarah Johnson
December 16, 2025
0.0k0

This comprehensive guide covers 50 essential Node.js interview questions that every backend developer should know. These questions cover fundamental concepts, event loop, async programming, modules, streams, and production-ready patterns commonly asked in technical interviews.

Core Concepts

Understanding Node.js core concepts is essential for any backend developer. These questions test your knowledge of the event loop, non-blocking I/O, and how Node.js handles concurrency.

Event Loop & Async Programming

The event loop is the heart of Node.js. Master these questions to demonstrate your understanding of asynchronous programming, promises, async/await, and callback patterns.

Modules & Package Management

Node.js uses CommonJS and ES modules for code organization. Understanding module systems, npm, and package management is crucial for building scalable applications.

Streams & File System

Streams are powerful for handling large data efficiently. These questions cover readable, writable, and transform streams, along with file system operations.

Production & Best Practices

Production-ready Node.js applications require proper error handling, security practices, performance optimization, and deployment strategies.

#Node.js#NodeJS#Node JS#Interview#Event Loop#Async#Backend#Node.js Interview#NodeJS Interview

Common Questions & Answers

Q1

What is Node.js and what are its main features?

A

Node.js is a JavaScript runtime built on Chrome's V8 engine that allows running JavaScript on the server. Main features include non-blocking I/O, event-driven architecture, single-threaded event loop, npm package ecosystem, and ability to build scalable network applications.

Q2

Explain the Node.js event loop and how it works.

A

The event loop is Node.js's mechanism for handling asynchronous operations. It has phases: timers (setTimeout/setInterval), pending callbacks, idle/prepare, poll (I/O operations), check (setImmediate), and close callbacks. It continuously processes these phases, executing callbacks when operations complete.

javascript
console.log('Start');
setTimeout(() => console.log('Timer'), 0);
setImmediate(() => console.log('Immediate'));
process.nextTick(() => console.log('NextTick'));
console.log('End');
// Output: Start, End, NextTick, Timer, Immediate
Q3

What is the difference between process.nextTick() and setImmediate()?

A

process.nextTick() executes before the event loop continues to the next phase, with highest priority. setImmediate() executes in the check phase of the next event loop iteration. Despite names, nextTick runs before setImmediate.

javascript
process.nextTick(() => console.log('1'));
setImmediate(() => console.log('2'));
console.log('3');
// Output: 3, 1, 2
Q4

How does Node.js handle blocking operations?

A

Node.js offloads blocking operations to libuv thread pool (default 4 threads) or system kernel. Operations like file I/O, DNS lookups use thread pool, while network I/O uses kernel async mechanisms. CPU-intensive tasks should use worker threads or child processes.

javascript
const fs = require('fs');
// Non-blocking async file read
fs.readFile('file.txt', 'utf8', (err, data) => {
  console.log(data);
});
console.log('This runs immediately');
Q5

What is the difference between require() and import?

A

require() is CommonJS (synchronous, used in Node.js), loads modules at runtime. import is ES6 modules (asynchronous, can be used with .mjs or type: "module"), supports static analysis, tree-shaking, and top-level await. CommonJS uses module.exports, ES6 uses export.

javascript
// CommonJS
const fs = require('fs');
module.exports = { readFile: fs.readFile };

// ES6 Modules
import fs from 'fs';
export { readFile: fs.readFile };
Q6

Explain callback hell and how to avoid it.

A

Callback hell occurs when multiple nested callbacks make code hard to read. Avoid it using promises, async/await, named functions, or libraries like async.js. Promises and async/await provide cleaner error handling and flow control.

javascript
// Callback hell
fs.readFile('file1', (err, data1) => {
  fs.readFile('file2', (err, data2) => {
    fs.writeFile('output', data1 + data2, () => {});
  });
});

// With async/await
const data1 = await fs.promises.readFile('file1');
const data2 = await fs.promises.readFile('file2');
await fs.promises.writeFile('output', data1 + data2);
Q7

What are Promises and how do they work?

A

Promises represent eventual completion of async operations. States: pending, fulfilled, rejected. They provide .then() for success, .catch() for errors, .finally() for cleanup. Promises chain and can be used with async/await for cleaner code.

javascript
const promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Success'), 1000);
});

promise
  .then(result => console.log(result))
  .catch(error => console.error(error))
  .finally(() => console.log('Done'));
Q8

What is async/await and how does it work?

A

async/await is syntactic sugar over promises. async functions return promises. await pauses execution until promise resolves. Errors are caught with try/catch. Makes asynchronous code look synchronous and easier to read.

javascript
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error:', error);
  }
}
Q9

What is the difference between spawn, exec, and fork in child_process?

A

spawn launches process, returns stream, non-blocking. exec runs command in shell, buffers output, has size limit. fork is spawn for Node.js processes, enables IPC. Use spawn for large output, exec for simple commands, fork for Node.js workers.

javascript
const { spawn, exec, fork } = require('child_process');

// spawn - streaming
const ls = spawn('ls', ['-la']);
ls.stdout.on('data', data => console.log(data));

// exec - buffered
exec('ls -la', (error, stdout) => console.log(stdout));

// fork - Node.js process
const child = fork('worker.js');
Q10

What are streams in Node.js and their types?

A

Streams handle data in chunks instead of loading all at once. Types: Readable (data source), Writable (data destination), Duplex (both), Transform (duplex with modification). Benefits: memory efficient, composable, handle backpressure. Examples: fs.createReadStream, HTTP requests.

javascript
const fs = require('fs');
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');

readStream.pipe(writeStream);
readStream.on('end', () => console.log('Done'));
Q11

What is middleware in Express.js?

A

Middleware are functions that execute during request-response cycle. They can modify req/res, end cycle, call next middleware. Types: application-level, router-level, error-handling, built-in. Order matters - executes sequentially.

javascript
const express = require('express');
const app = express();

app.use(express.json());
app.use((req, res, next) => {
  console.log('Middleware');
  next();
});

app.get('/', (req, res) => res.send('Hello'));
Q12

How do you handle errors in Node.js?

A

Use try/catch for async/await, .catch() for promises, error-first callbacks, error middleware in Express, process.on('uncaughtException'), process.on('unhandledRejection'). Always handle errors explicitly, log them, and provide meaningful messages.

javascript
// Try/catch
try {
  await riskyOperation();
} catch (error) {
  console.error(error);
}

// Promise catch
promise.catch(error => console.error(error));

// Error middleware
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message });
});
Q13

What is the difference between cluster and worker_threads?

A

Cluster creates separate Node.js processes, shares nothing, uses IPC. Worker threads share memory via SharedArrayBuffer, lighter weight, better for CPU tasks. Cluster for isolation, worker threads for parallelism within process.

javascript
// Cluster
const cluster = require('cluster');
if (cluster.isMaster) {
  cluster.fork();
} else {
  // Worker code
}

// Worker threads
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js');
Q14

What is the purpose of package.json?

A

package.json defines project metadata, dependencies (dependencies, devDependencies), scripts, version, entry point, license, engines. npm uses it for installs, scripts, publishing. Essential for Node.js project management and dependency tracking.

json
{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node index.js",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.18.0"
  }
}
Q15

What is the difference between dependencies and devDependencies?

A

dependencies are required for production runtime. devDependencies are only needed during development (testing, building, linting). npm install --production installs only dependencies. Examples: express in dependencies, jest in devDependencies.

json
{
  "dependencies": {
    "express": "^4.18.0"
  },
  "devDependencies": {
    "jest": "^29.0.0",
    "eslint": "^8.0.0"
  }
}
Q16

What is Buffer in Node.js?

A

Buffer is global class for handling binary data. Represents fixed-size memory allocation outside V8 heap. Used for file I/O, network operations, crypto. Created with Buffer.from(), Buffer.alloc(), Buffer.allocUnsafe(). Immutable in modern Node.js.

javascript
const buf = Buffer.from('Hello', 'utf8');
console.log(buf.toString()); // Hello
console.log(buf.length); // 5

const buf2 = Buffer.alloc(10);
buf2.write('Node.js');
Q17

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

A

setImmediate() executes in check phase of current event loop iteration. setTimeout() executes in timers phase after specified delay. In I/O cycle, setImmediate runs before setTimeout(0). Outside I/O, order depends on performance.

javascript
setTimeout(() => console.log('setTimeout'), 0);
setImmediate(() => console.log('setImmediate'));
// Order can vary, but setImmediate often runs first in I/O cycle
Q18

How do you create a RESTful API in Express?

A

Use Express router, define routes for HTTP methods (GET, POST, PUT, DELETE), use middleware for parsing (express.json()), validation, authentication. Follow REST conventions: resource-based URLs, proper status codes, JSON responses.

javascript
const express = require('express');
const app = express();
app.use(express.json());

app.get('/users', (req, res) => {
  res.json({ users: [] });
});

app.post('/users', (req, res) => {
  res.status(201).json({ id: 1, ...req.body });
});

app.listen(3000);
Q19

What is the purpose of __dirname and __filename?

A

__dirname is directory name of current module. __filename is absolute path of current module file. Both are CommonJS globals. In ES modules, use import.meta.url with fileURLToPath() and dirname() from path module.

javascript
// CommonJS
console.log(__dirname); // /path/to/dir
console.log(__filename); // /path/to/dir/file.js

// ES Modules
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Q20

What is event-driven programming in Node.js?

A

Event-driven programming uses events and event handlers. Node.js is built on event-driven architecture with EventEmitter. Components emit events, listeners respond. Enables non-blocking, reactive programming. Examples: HTTP server, file streams, custom events.

javascript
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const emitter = new MyEmitter();

emitter.on('event', (data) => {
  console.log('Event:', data);
});

emitter.emit('event', 'Hello');
Q21

What is the difference between readFile and readFileSync?

A

readFile is asynchronous, non-blocking, uses callback. readFileSync is synchronous, blocking, returns result directly. Use readFile for better performance. readFileSync only for scripts or when blocking is acceptable.

javascript
const fs = require('fs');

// Async
fs.readFile('file.txt', 'utf8', (err, data) => {
  console.log(data);
});

// Sync
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
Q22

What is process.env and how is it used?

A

process.env is object containing environment variables. Set via command line, .env files (with dotenv), or system. Used for configuration: API keys, database URLs, feature flags. Access with process.env.VARIABLE_NAME. Never commit sensitive values.

javascript
// Set: NODE_ENV=production node app.js
// Or use dotenv: require('dotenv').config();

const port = process.env.PORT || 3000;
const dbUrl = process.env.DATABASE_URL;

console.log(process.env.NODE_ENV);
Q23

What is the purpose of npm scripts?

A

npm scripts run commands defined in package.json scripts section. Access with npm run script-name. Can chain commands, use pre/post hooks, access node_modules/.bin. Common: start, test, build, dev. Simplifies common tasks.

json
{
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest",
    "build": "webpack"
  }
}
// Run: npm run dev
Q24

What is middleware chaining in Express?

A

Middleware execute sequentially in order defined. Each calls next() to pass to next middleware. Can modify req/res, end response, or continue chain. Order matters - authentication before routes, error handling last.

javascript
app.use(middleware1);
app.use('/api', middleware2);
app.get('/users', middleware3, (req, res) => {
  res.json({ users: [] });
});

function middleware1(req, res, next) {
  console.log('1');
  next();
}
Q25

What is the difference between exports and module.exports?

A

module.exports is the actual object exported. exports is reference to module.exports. Assigning to exports doesn't work - must use module.exports. Common pattern: module.exports = { ... } or exports.property = value.

javascript
// Both work
module.exports = { name: 'John' };
exports.name = 'John';

// This doesn't work
exports = { name: 'John' };

// Use this
module.exports = { name: 'John' };
Q26

How do you handle file uploads in Express?

A

Use multer middleware for multipart/form-data. Configure storage (disk/memory), file filters, size limits. Access files via req.files or req.file. Save to disk or process in memory. Validate file type and size.

javascript
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('file'), (req, res) => {
  res.json({ file: req.file });
});

// Multiple files
app.post('/upload', upload.array('files', 5), ...);
Q27

What is the purpose of util.promisify?

A

util.promisify converts callback-based functions to promise-based. Takes function with (err, result) callback, returns function returning promise. Enables using async/await with callback APIs. Useful for fs, crypto, and other Node.js modules.

javascript
const util = require('util');
const fs = require('fs');

const readFile = util.promisify(fs.readFile);

async function read() {
  const data = await readFile('file.txt', 'utf8');
  console.log(data);
}
Q28

What is the difference between app.listen() and server.listen()?

A

app.listen() is Express shortcut that calls http.createServer(app) and server.listen(). server.listen() is Node.js HTTP server method. app.listen() returns server instance. Use server.listen() for HTTPS or more control.

javascript
// Express shortcut
const server = app.listen(3000);

// Direct server
const http = require('http');
const server = http.createServer(app);
server.listen(3000);
Q29

What is the purpose of body-parser in Express?

A

body-parser parses incoming request bodies. Express 4.16+ includes it as express.json() and express.urlencoded(). Parses JSON, URL-encoded, and other formats. Makes req.body available. Essential for POST/PUT requests.

javascript
const express = require('express');
const app = express();

app.use(express.json()); // Parse JSON
app.use(express.urlencoded({ extended: true })); // Parse form data

app.post('/users', (req, res) => {
  console.log(req.body); // Parsed data
});
Q30

What is the difference between process.nextTick() and queueMicrotask()?

A

Both execute before event loop continues. process.nextTick() is Node.js-specific, highest priority, runs in all phases. queueMicrotask() is web standard, runs after nextTick, before promises. Use nextTick for Node.js, queueMicrotask for cross-platform.

javascript
process.nextTick(() => console.log('1'));
queueMicrotask(() => console.log('2'));
Promise.resolve().then(() => console.log('3'));
// Output: 1, 2, 3
Q31

How do you implement authentication in Express?

A

Use middleware like passport.js, JWT tokens, or session-based auth. JWT: generate token on login, verify in middleware, attach to requests. Sessions: use express-session, store in memory/Redis. OAuth: use passport strategies.

javascript
const jwt = require('jsonwebtoken');

function authenticate(req, res, next) {
  const token = req.headers.authorization;
  try {
    const decoded = jwt.verify(token, 'secret');
    req.user = decoded;
    next();
  } catch (err) {
    res.status(401).json({ error: 'Unauthorized' });
  }
}

app.get('/protected', authenticate, (req, res) => {
  res.json({ data: 'Protected' });
});
Q32

What is the purpose of path module?

A

path module provides utilities for working with file paths. Methods: join() (combine paths), resolve() (absolute path), dirname() (directory), basename() (filename), extname() (extension). Handles cross-platform path differences (Windows vs Unix).

javascript
const path = require('path');

path.join('/users', 'john', 'file.txt'); // /users/john/file.txt
path.resolve('file.txt'); // Absolute path
path.dirname('/users/john/file.txt'); // /users/john
path.basename('/users/john/file.txt'); // file.txt
path.extname('file.txt'); // .txt
Q33

What is the difference between require() and require.resolve()?

A

require() loads and executes module, returns exports. require.resolve() only resolves module path without loading. Returns absolute path. Useful for finding module location, checking if module exists, or getting paths for configuration.

javascript
const express = require('express'); // Loads module
const expressPath = require.resolve('express'); // Returns path
console.log(expressPath); // /path/to/node_modules/express/index.js
Q34

What is the purpose of crypto module?

A

crypto provides cryptographic functionality. Methods: createHash() (hashing), createHmac() (HMAC), randomBytes() (random data), createCipher() (encryption), createSign() (signing). Used for passwords, tokens, encryption, security. Essential for secure applications.

javascript
const crypto = require('crypto');

const hash = crypto.createHash('sha256')
  .update('password')
  .digest('hex');

const random = crypto.randomBytes(16).toString('hex');

const hmac = crypto.createHmac('sha256', 'secret')
  .update('data')
  .digest('hex');
Q35

What is the difference between cluster and PM2?

A

Cluster is Node.js built-in module for multi-process. PM2 is process manager with clustering, monitoring, auto-restart, logging. PM2 uses cluster internally but adds features: zero-downtime reload, monitoring dashboard, ecosystem file. Use PM2 for production.

javascript
// Cluster
const cluster = require('cluster');
if (cluster.isMaster) {
  for (let i = 0; i < 4; i++) cluster.fork();
}

// PM2: pm2 start app.js -i 4
// Or: pm2 ecosystem.config.js
Q36

What is the purpose of os module?

A

os module provides operating system utilities. Methods: platform() (OS type), arch() (architecture), cpus() (CPU info), totalmem() (total memory), freemem() (free memory), hostname(), networkInterfaces(). Useful for system information, monitoring, platform-specific code.

javascript
const os = require('os');

console.log(os.platform()); // linux, darwin, win32
console.log(os.arch()); // x64, arm
console.log(os.cpus().length); // CPU cores
console.log(os.totalmem()); // Total memory
console.log(os.freemem()); // Free memory
Q37

What is the difference between http and https modules?

A

http creates HTTP servers (port 80). https creates HTTPS servers (port 443) with SSL/TLS encryption. https requires certificate options (key, cert). Both have same API. Use https for secure connections, sensitive data, production apps.

javascript
const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem')
};

https.createServer(options, (req, res) => {
  res.end('Hello');
}).listen(443);
Q38

What is the purpose of querystring module?

A

querystring parses and formats URL query strings. Methods: parse() (string to object), stringify() (object to string), escape() (encode), unescape() (decode). Useful for handling URL parameters, form data, API query strings.

javascript
const querystring = require('querystring');

const params = querystring.parse('name=John&age=30');
// { name: 'John', age: '30' }

const query = querystring.stringify({ name: 'John', age: 30 });
// 'name=John&age=30'
Q39

What is the difference between readFile and createReadStream?

A

readFile loads entire file into memory, good for small files. createReadStream reads file in chunks, memory efficient for large files. Streams handle backpressure, can be piped. Use streams for large files, videos, logs.

javascript
const fs = require('fs');

// Loads all in memory
fs.readFile('large.txt', (err, data) => {
  console.log(data);
});

// Streams in chunks
const stream = fs.createReadStream('large.txt');
stream.on('data', chunk => console.log(chunk));
Q40

What is the purpose of url module?

A

url module parses and formats URLs. Methods: parse() (legacy), new URL() (modern), format(). Provides properties: protocol, hostname, pathname, search, hash. Essential for routing, API endpoints, URL manipulation.

javascript
const { URL } = require('url');

const url = new URL('https://example.com/path?name=John');
console.log(url.hostname); // example.com
console.log(url.pathname); // /path
console.log(url.searchParams.get('name')); // John
Q41

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

A

app.use() applies middleware to all HTTP methods and paths (or specified paths). app.get() handles only GET requests for specific routes. app.use() for middleware, app.get() for route handlers. Order matters in both.

javascript
app.use(express.json()); // Middleware for all routes
app.use('/api', apiRouter); // Middleware for /api/*

app.get('/users', (req, res) => { // Only GET /users
  res.json({ users: [] });
});
Q42

What is the purpose of zlib module?

A

zlib provides compression/decompression using gzip, deflate, brotli. Methods: createGzip(), createGunzip(), createDeflate(). Used for HTTP compression, file compression, reducing bandwidth. Express can use compression middleware.

javascript
const zlib = require('zlib');
const fs = require('fs');

fs.createReadStream('file.txt')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('file.txt.gz'));
Q43

What is the difference between process.exit() and server.close()?

A

process.exit() immediately terminates Node.js process. server.close() stops accepting new connections, waits for existing to close, then emits close event. Use server.close() for graceful shutdown, process.exit() for forced termination.

javascript
server.close(() => {
  console.log('Server closed');
  process.exit(0);
});

// Graceful shutdown
process.on('SIGTERM', () => {
  server.close(() => process.exit(0));
});
Q44

What is the purpose of assert module?

A

assert provides assertion testing. Methods: equal(), strictEqual(), deepEqual(), ok(). Throws AssertionError if condition fails. Used for testing, validation, debugging. Prefer testing frameworks (Jest, Mocha) for production tests.

javascript
const assert = require('assert');

assert.strictEqual(1 + 1, 2);
assert.deepEqual({ a: 1 }, { a: 1 });
assert.ok(value, 'Value should be truthy');
Q45

What is the difference between global and window objects?

A

global is Node.js global object (like window in browser). Contains global functions, classes, objects. In browser, global is window. In Node.js, global is separate. Use global for Node.js, window for browser. Avoid polluting global scope.

javascript
// Node.js
global.myVar = 'value';
console.log(global.myVar);

// Browser
window.myVar = 'value';
console.log(window.myVar);
Q46

What is the purpose of dns module?

A

dns provides DNS lookup functionality. Methods: lookup() (hostname to IP), resolve() (DNS records), reverse() (IP to hostname). Can use system resolver or custom DNS servers. Used for hostname resolution, network diagnostics.

javascript
const dns = require('dns');

dns.lookup('example.com', (err, address) => {
  console.log(address); // IP address
});

dns.resolve('example.com', 'A', (err, addresses) => {
  console.log(addresses); // Array of IPs
});
Q47

What is the difference between JSON.parse() and JSON.stringify()?

A

JSON.parse() converts JSON string to JavaScript object. JSON.stringify() converts JavaScript object to JSON string. parse() for deserialization, stringify() for serialization. Both can throw errors for invalid input.

javascript
const obj = { name: 'John', age: 30 };
const json = JSON.stringify(obj); // '{"name":"John","age":30}'
const parsed = JSON.parse(json); // { name: 'John', age: 30 }
Q48

What is the purpose of timers module?

A

timers provides setTimeout(), setInterval(), setImmediate(), clearTimeout(), clearInterval(). Global in Node.js, but can be imported. Used for delayed execution, periodic tasks, scheduling. Returns timer objects for cancellation.

javascript
const { setTimeout, setInterval } = require('timers');

const timer1 = setTimeout(() => console.log('Done'), 1000);
const timer2 = setInterval(() => console.log('Tick'), 1000);

clearTimeout(timer1);
clearInterval(timer2);
Q49

What is the difference between development and production environments?

A

Development: detailed errors, hot reload, verbose logging, unminified code, debug tools. Production: error handling, optimized code, minimal logging, security headers, monitoring. Set via NODE_ENV. Use different configs, databases, logging levels.

javascript
const isDev = process.env.NODE_ENV !== 'production';

if (isDev) {
  console.log('Debug info');
  app.use(errorHandler);
} else {
  app.use(productionErrorHandler);
}
Q50

What is the purpose of vm module?

A

vm provides V8 virtual machine context for executing JavaScript. Methods: createContext(), runInContext(), runInNewContext(). Creates isolated execution environment. Use for sandboxing, code evaluation, templating. Be careful with security.

javascript
const vm = require('vm');

const context = { x: 10 };
vm.createContext(context);

const code = 'x += 1; y = 2;';
vm.runInContext(code, context);

console.log(context); // { x: 11, y: 2 }