Top 50+ NodeJS Interview Questions for Freshers & Senior Developers
This comprehensive guide covers the most frequently asked Node.js interview questions — from basic concepts to advanced topics. Whether you're a fresher preparing for your first interview or an experienced developer aiming for a senior role, these questions will help you succeed.
Section 1: Node.js Basics
Q1. What is Node.js?
Answer: Node.js is an open-source, cross-platform JavaScript runtime environment built on Chrome's V8 engine. It allows JavaScript to run on the server side, enabling developers to build scalable, high-performance applications.
Q2. Is Node.js single-threaded or multi-threaded?
Answer: Node.js is single-threaded for JavaScript execution (using the event loop) but uses a thread pool (via libuv) for I/O operations. The main thread handles all requests, while background threads handle I/O operations asynchronously.
Q3. What is the difference between Node.js and JavaScript?
Answer: JavaScript is a programming language that runs in browsers. Node.js is a runtime environment that executes JavaScript outside the browser, providing APIs for file system, networking, and other server-side operations.
Q4. What is npm?
Answer: npm (Node Package Manager) is the default package manager for Node.js. It allows developers to install, manage, and share reusable packages (libraries) from the npm registry — the largest software registry in the world.
Q5. What is the difference between require and import?
Answer: require is the CommonJS module system (synchronous, dynamic), while import is the ES module system (asynchronous, static). ES modules support tree shaking and better static analysis.
Section 2: Event Loop & Asynchronous Programming
Q6. What is the event loop in Node.js?
Answer: The event loop is a mechanism that allows Node.js to perform non-blocking I/O operations despite being single-threaded. It continuously checks the call stack and callback queue, moving callbacks to the stack when it's empty.
Q7. What are the phases of the event loop?
Answer: The event loop has six phases:
- Timers: Executes callbacks scheduled by setTimeout/setInterval.
- Pending Callbacks: Executes I/O callbacks (errors).
- Idle/Prepare: Internal use only.
- Poll: Retrieves new I/O events and executes callbacks.
- Check: Executes setImmediate() callbacks.
- Close Callbacks: Executes close/cleanup callbacks.
Q8. What is the difference between setTimeout and setImmediate?
Answer: setImmediate executes in the "Check" phase after I/O events, while setTimeout(fn, 0) executes in the "Timers" phase. In practice, the order depends on when the event loop enters each phase, but setImmediate generally executes before setTimeout(fn, 0).
Q9. What is process.nextTick()?
Answer: process.nextTick() schedules a callback to be executed in the current phase of the event loop, immediately after the current operation completes — before the next event loop phase starts.
Q10. What is "callback hell" and how do you avoid it?
Answer: "Callback hell" is deeply nested callbacks that make code hard to read and maintain. Avoid it using:
- Promises with async/await
- Modularization (breaking into smaller functions)
- Using libraries like async.js
Q11. What is the difference between blocking and non-blocking code in Node.js?
Answer: Blocking code (e.g., fs.readFileSync) stops the event loop until the operation completes. Non-blocking code (e.g., fs.readFile) delegates the operation to libuv and continues execution, allowing other operations to run while waiting for I/O.
Section 3: Core Modules
Q12. What are the core modules in Node.js?
Answer: Core modules are built-in modules that come with Node.js installation:
fs— File system operationspath— Path manipulationhttp/https— HTTP/HTTPS serversos— Operating system infoevents— Event emittercrypto— Cryptographyutil— Utility functionsstream— Streaming data
Q13. What is the fs module used for?
Answer: The fs (File System) module provides an API for interacting with the file system — reading/writing files, creating/deleting directories, getting file stats, watching for changes, and streaming file data.
Q14. What is the events module and how does it work?
Answer: The events module provides the EventEmitter class, which implements the observer pattern. Objects can emit events and listeners can subscribe to those events.
const EventEmitter = require('events');
const emitter = new EventEmitter();
emitter.on('event', (data) => console.log(data));
emitter.emit('event', 'Hello!');
Q15. What is the crypto module used for?
Answer: The crypto module provides cryptographic functionality — hashing (SHA, MD5), HMAC, random number generation, encryption/decryption (AES), and password-based key derivation (PBKDF2).
Section 4: Express.js & Routing
Q16. What is Express.js?
Answer: Express.js is a minimal, unopinionated web framework for Node.js. It provides a thin layer of fundamental web application features — routing, middleware, templating, and HTTP utilities — without obscuring Node.js features.
Q17. What is middleware in Express?
Answer: Middleware is a function that has access to the request and response objects and the next middleware function. It can:
- Execute any code
- Modify the request/response
- End the request-response cycle
- Call the next middleware
Q18. What are the types of middleware in Express?
Answer: Express has several types:
- Application-level:
app.use() - Router-level:
router.use() - Error-handling:
app.use((err, req, res, next) => {}) - Built-in:
express.json(),express.static() - Third-party:
cors(),helmet()
Q19. How do you handle errors in Express.js?
Answer: Use error-handling middleware with four parameters:
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
error: err.message || 'Internal server error'
});
});
Q20. What is the purpose of express.Router()?
Answer: express.Router() creates modular, mountable route handlers. It helps organize routes into separate modules, making the codebase more maintainable and scalable.
Section 5: Databases & Authentication
Q21. What is JWT and how is it used in Node.js?
Answer: JWT (JSON Web Token) is a compact, URL-safe token format for secure data exchange. In Node.js, it's used for stateless authentication:
const jwt = require('jsonwebtoken');
const token = jwt.sign({ userId: 123 }, 'secret', { expiresIn: '1h' });
const decoded = jwt.verify(token, 'secret');
Q22. What is the difference between authentication and authorization?
Answer: Authentication verifies who the user is (login), while authorization determines what the user can do (roles, permissions). Authentication always comes before authorization.
Q23. How do you hash passwords in Node.js?
Answer: Use bcrypt with high salt rounds (12+):
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);
const isValid = await bcrypt.compare(password, hash);
Q24. What is the difference between SQL and NoSQL databases in Node.js?
Answer: SQL databases (PostgreSQL, MySQL) are relational with schemas, ACID transactions, and SQL queries. NoSQL databases (MongoDB) are schema-less, document-based, and horizontally scalable. Node.js works well with both, but MongoDB is often preferred for its JSON-like document structure.
Section 6: Streaming & Performance
Q25. What are streams in Node.js?
Answer: Streams are objects that allow reading/writing data in chunks rather than loading the entire data into memory. They're ideal for handling large files, network data, and real-time processing.
Q26. What are the types of streams in Node.js?
Answer: There are four types:
- Readable: Reading data (e.g.,
fs.createReadStream) - Writable: Writing data (e.g.,
fs.createWriteStream) - Duplex: Both readable and writable (e.g.,
net.Socket) - Transform: Duplex streams that modify data (e.g.,
zlib.createGzip)
Q27. What is the difference between pipe and pipeline?
Answer: pipe is the older method for piping streams; it doesn't handle errors well and can cause memory leaks. pipeline (from stream module) is the modern approach with better error handling and cleanup.
Q28. How do you improve Node.js performance?
Answer:
- Use asynchronous/non-blocking code
- Use clustering to utilize multiple CPU cores
- Implement caching (Redis, in-memory)
- Use streams for large data
- Optimize database queries
- Use a reverse proxy (Nginx)
- Enable HTTP/2
- Use production-grade process managers (PM2)
Section 7: Security
Q29. How do you secure a Node.js application?
Answer:
- Use Helmet.js for security headers
- Implement rate limiting
- Validate user input (express-validator)
- Sanitize output (prevent XSS)
- Use HTTPS in production
- Store secrets in environment variables
- Use JWT for authentication
- Implement CORS properly
- Keep dependencies updated
Q30. What is CORS and how is it handled in Express?
Answer: CORS (Cross-Origin Resource Sharing) is a security mechanism that restricts cross-origin requests. In Express, use the cors package:
const cors = require('cors');
app.use(cors({
origin: 'https://myapp.com',
credentials: true
}));
Section 8: Advanced Concepts
Q31. What is clustering in Node.js?
Answer: Clustering allows Node.js to utilize multiple CPU cores by creating child processes (workers) that share the same server port. This is achieved using the cluster module or process managers like PM2.
const cluster = require('cluster');
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < require('os').cpus().length; i++) {
cluster.fork();
}
} else {
// Worker process
require('./server.js');
}
Q32. What are Worker Threads?
Answer: Worker Threads (introduced in Node.js 10.5.0) allow running JavaScript in parallel on separate threads, useful for CPU-intensive tasks. Unlike clustering, Worker Threads share memory.
const { Worker } = require('worker_threads');
const worker = new Worker(`
const { parentPort } = require('worker_threads');
// CPU-intensive work
parentPort.postMessage(result);
`, { eval: true });
worker.on('message', (result) => console.log(result));
Q33. What is the difference between clustering and Worker Threads?
Answer: Clustering creates separate processes (IPC communication), ideal for handling HTTP requests across CPU cores. Worker Threads share memory (more efficient for CPU tasks) but require careful management of shared state.
Q34. What is the libuv library?
Answer: libuv is a cross-platform C++ library that implements the event loop, thread pool, and asynchronous I/O in Node.js. It provides the underlying mechanism for non-blocking operations.
Q35. What is the V8 engine?
Answer: V8 is Google's open-source JavaScript engine, written in C++. It compiles JavaScript to native machine code (JIT compilation) and handles memory management and garbage collection. Node.js uses V8 to execute JavaScript.
Q36. How does garbage collection work in Node.js?
Answer: V8 uses a generational garbage collector. It divides memory into generations — the young generation (new objects) and the old generation (long-lived objects). The young generation is collected frequently (Scavenge), while the old generation uses Mark-Sweep-Compact.
Q37. What is the difference between process.env and process.argv?
Answer: process.env contains environment variables (e.g., process.env.PORT). process.argv contains command-line arguments passed when starting the Node.js process.
Q38. What is the difference between require.resolve and require.cache?
Answer: require.resolve resolves the path of a module without loading it. require.cache is an object containing all cached module objects, allowing you to invalidate the cache.
Section 9: Testing & Debugging
Q39. What testing frameworks are commonly used in Node.js?
Answer: Popular frameworks include:
- Jest: Zero-config, built-in assertions, mocking
- Mocha: Flexible, many assertion libraries
- Jasmine: BDD-style, built-in assertions
- AVA: Concurrent test execution
- Supertest: HTTP assertions
Q40. How do you debug a Node.js application?
Answer:
node --inspect app.jsand use Chrome DevTools- VS Code's built-in debugger
- Logging with
console.logor debug libraries - Use
--inspect-brkto break at the start - Use APM tools for production debugging
Section 10: Deployment & Production
Q41. How do you deploy a Node.js application in production?
Answer:
- Use a process manager (PM2, Forever)
- Use a reverse proxy (Nginx, Apache)
- Containerize with Docker
- Use cloud platforms (AWS, Heroku, DigitalOcean)
- Set environment variables
- Enable logging and monitoring
- Implement CI/CD pipelines
Q42. What is PM2 and why is it used?
Answer: PM2 is a production process manager for Node.js. It provides features like:
- Auto-restart on crashes
- Cluster mode (multi-core support)
- Zero-downtime reloads
- Log management
- Monitoring and health checks
Q43. What is the difference between development and production dependencies?
Answer: Development dependencies (--save-dev) are only needed during development (testing, building, linting). Production dependencies (--save) are required to run the application. Use npm install --production to install only production dependencies.
Q44. What is the NODE_ENV environment variable used for?
Answer: NODE_ENV is a standard environment variable that indicates the environment (development, production, test). It's used to enable/disable features like logging, debugging, and caching.
Section 11: Real-Time & WebSockets
Q45. What is Socket.IO?
Answer: Socket.IO is a library that enables real-time, bidirectional communication between clients and servers. It uses WebSocket when available and falls back to other transports (long polling, etc.) for compatibility.
Q46. How does Socket.IO handle reconnection?
Answer: Socket.IO automatically handles reconnection with exponential backoff. It stores messages while disconnected and sends them after reconnection.
const socket = io('https://api.example.com', {
reconnection: true,
reconnectionAttempts: 10,
reconnectionDelay: 1000
});
Q47. What are rooms and namespaces in Socket.IO?
Answer: Namespaces allow separating concerns (e.g., /chat, /notifications). Rooms allow grouping clients within a namespace for targeted messaging.
Section 12: Common Interview Coding Challenges
Q48. Write a function to read a file asynchronously in Node.js.
const fs = require('fs').promises;
async function readFile(filePath) {
try {
const data = await fs.readFile(filePath, 'utf8');
return data;
} catch (err) {
console.error('Error reading file:', err.message);
return null;
}
}
Q49. Write a simple HTTP server in Node.js.
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World!');
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
Q50. Write a function that uses async/await with error handling.
async function fetchUserData(userId) {
try {
const user = await User.findById(userId);
if (!user) {
throw new Error('User not found');
}
const posts = await Post.find({ userId });
return { user, posts };
} catch (err) {
console.error('Error fetching user data:', err.message);
return null;
}
}
Q51. Write a middleware that logs request details.
const loggerMiddleware = (req, res, next) => {
const start = Date.now();
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url} - ${res.statusCode} (${duration}ms)`);
});
next();
};
app.use(loggerMiddleware);
Q52. Write a simple Express route with route parameters.
app.get('/api/users/:id', (req, res) => {
const { id } = req.params;
// Fetch user by ID
res.json({ userId: id, name: `User ${id}` });
});
Q53. Write a function that uses the event emitter.
const EventEmitter = require('events');
class OrderService extends EventEmitter {
createOrder(order) {
this.emit('order.created', order);
// Process order...
this.emit('order.processed', order);
}
}
const service = new OrderService();
service.on('order.created', (order) => console.log('Order created:', order));
Q54. Write a function that creates a JWT token.
const jwt = require('jsonwebtoken');
function generateToken(user) {
return jwt.sign(
{ userId: user.id, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);
}
Q55. Write a function that uses streams to process a large file.
const fs = require('fs');
const { pipeline } = require('stream');
const { promisify } = require('util');
const pipelineAsync = promisify(pipeline);
async function processLargeFile(source, destination) {
const readStream = fs.createReadStream(source);
const writeStream = fs.createWriteStream(destination);
await pipelineAsync(readStream, writeStream);
console.log('File processed successfully');
}
Q56. Write a function that implements rate limiting for an API.
const rateLimit = new Map();
function rateLimiter(req, res, next) {
const ip = req.ip;
const now = Date.now();
const window = 60000; // 1 minute
const maxRequests = 100;
if (!rateLimit.has(ip)) {
rateLimit.set(ip, []);
}
const requests = rateLimit.get(ip)
.filter(time => time > now - window);
if (requests.length >= maxRequests) {
return res.status(429).json({ error: 'Too many requests' });
}
requests.push(now);
rateLimit.set(ip, requests);
next();
}
Q57. Write a function that connects to MongoDB using Mongoose.
const mongoose = require('mongoose');
async function connectDB() {
try {
await mongoose.connect(process.env.MONGODB_URI);
console.log('✅ Connected to MongoDB');
} catch (err) {
console.error('❌ MongoDB connection error:', err);
process.exit(1);
}
}
Q58. Write a function that implements a simple cache using Map.
class Cache {
constructor(ttl = 60000) {
this.cache = new Map();
this.ttl = ttl;
}
set(key, value) {
this.cache.set(key, {
value,
expires: Date.now() + this.ttl
});
}
get(key) {
const entry = this.cache.get(key);
if (!entry || entry.expires < Date.now()) {
this.cache.delete(key);
return null;
}
return entry.value;
}
}
Q59. Write a function that handles graceful shutdown in a Node.js app.
process.on('SIGTERM', () => {
console.log('📦 SIGTERM received. Shutting down gracefully...');
server.close(() => {
console.log('✅ Server closed');
db.disconnect();
process.exit(0);
});
});
process.on('SIGINT', () => {
console.log('📦 SIGINT received. Shutting down...');
process.exit(0);
});
Q60. Write a function that logs unhandled promise rejections.
process.on('unhandledRejection', (reason, promise) => {
console.error('❌ Unhandled Rejection at:', promise);
console.error('❌ Reason:', reason);
// Optionally exit or continue
});
Section 13: Quick Reference — Key Concepts
| Concept | Description | When to Use |
|---|---|---|
| Event Loop | Non-blocking I/O mechanism | Every Node.js application |
| Clustering | Utilize multi-core CPUs | High-traffic production apps |
| Worker Threads | CPU-intensive tasks | Image processing, heavy computation |
| Streams | Process data in chunks | Large files, network data |
| JWT | Stateless authentication | APIs, microservices |
| Socket.IO | Real-time communication | Chat, live updates, gaming |
| PM2 | Production process manager | Deployment, monitoring |
| Helmet.js | Security headers | Every Express app |
🎉 Congratulations! You've Completed the Node.js Series! 🎉
You now have a solid foundation in Node.js development — from architecture and core modules to production-ready applications. Keep practicing, stay curious, and never stop learning!
Ready to master Node.js?
Build scalable, high-performance backend applications with Node.js. Learn from industry experts with hands-on projects.
.png)