Top Interview Questions
Node.js is a powerful, open-source runtime environment that allows developers to run JavaScript outside of the browser. Introduced in 2009 by Ryan Dahl, Node.js has had a profound impact on the way web applications are built and deployed. Traditionally, JavaScript was used only for client-side scripting, meaning it could only run in web browsers to make websites interactive. Node.js changed this paradigm by enabling JavaScript to be executed on the server, opening the door for full-stack development using a single language.
At its core, Node.js is built on Google Chrome’s V8 JavaScript engine, which converts JavaScript code into highly efficient machine code. This allows Node.js applications to run very quickly, making it suitable for handling large volumes of requests with low latency. Unlike traditional server-side environments, which often use multithreading to handle multiple requests simultaneously, Node.js uses a single-threaded, event-driven architecture. This design allows it to handle thousands of concurrent connections without creating new threads for each request, which reduces memory usage and improves performance.
One of the key features of Node.js is its non-blocking, asynchronous nature. In most traditional server environments, code execution is blocking, meaning the server must wait for one operation to complete before moving on to the next. For example, reading a file or fetching data from a database would temporarily halt the server until the operation finished. Node.js, however, uses asynchronous programming and callbacks (or promises and async/await in modern JavaScript) to handle tasks without blocking the main thread. This makes Node.js particularly efficient for I/O-intensive applications, such as chat applications, real-time gaming, streaming services, and APIs.
Node.js also introduced the concept of a package manager for JavaScript called npm (Node Package Manager). npm is one of the largest ecosystems of open-source libraries in the world, offering thousands of modules that developers can easily integrate into their projects. These modules provide functionality for everything from handling HTTP requests to working with databases, encryption, authentication, and much more. The availability of npm packages has greatly accelerated development, as developers no longer need to write common functionalities from scratch.
Another significant advantage of Node.js is that it allows developers to use JavaScript for both client-side and server-side development. This unified language approach simplifies the development process because developers can write full-stack applications without needing to switch between languages like JavaScript and PHP, Python, or Ruby. This reduces context-switching, allows for better code reuse, and makes it easier for teams to maintain projects. Full-stack JavaScript frameworks such as MEAN (MongoDB, Express, Angular, Node.js) and MERN (MongoDB, Express, React, Node.js) leverage this principle to build scalable web applications efficiently.
Node.js is particularly well-suited for building real-time applications. Real-time applications require the server and client to exchange data instantly, such as in messaging apps, online collaboration tools, or live tracking systems. Node.js achieves this through technologies like WebSockets, which maintain a continuous, open connection between the client and the server. This enables data to flow instantly in both directions without the need for repeated HTTP requests, resulting in faster and more responsive user experiences.
Despite its advantages, Node.js is not without challenges. Its single-threaded nature, while efficient for I/O operations, can become a limitation for CPU-intensive tasks, such as large computations or data processing. Performing heavy computations on the main thread can block the event loop, slowing down the entire application. To address this, developers can use worker threads or offload intensive tasks to separate processes, but this requires careful planning and design.
Security is another critical aspect to consider when working with Node.js. Like any server-side platform, Node.js applications can be vulnerable to attacks such as cross-site scripting (XSS), SQL injection, and denial-of-service (DoS) attacks if best practices are not followed. Fortunately, Node.js has a strong community that maintains security guidelines, and developers can use libraries like Helmet or implement secure coding practices to protect their applications.
Node.js has been widely adopted by companies of all sizes, from startups to tech giants. Many high-profile organizations rely on Node.js for their production systems, including Netflix, LinkedIn, PayPal, Walmart, and Uber. These companies use Node.js for its speed, scalability, and efficiency in handling large numbers of simultaneous connections. Node.js also integrates well with modern cloud platforms and microservices architectures, making it a popular choice for building distributed systems.
Another key feature of Node.js is its extensibility. Developers can create custom modules or extend existing ones to meet the specific needs of their applications. The modular structure of Node.js encourages clean and maintainable code, as functionality can be separated into smaller, reusable components. This modularity is particularly important for large-scale applications, where code organization and maintainability are critical for long-term success.
Node.js also promotes the use of modern JavaScript features, such as ES6 modules, async/await, template literals, arrow functions, and destructuring. This allows developers to write cleaner, more readable, and maintainable code compared to older callback-based approaches. Over time, Node.js has continued to evolve alongside the JavaScript language, supporting new features and standards to improve developer productivity and application performance.
For beginners, Node.js can be an excellent entry point into server-side development. Its strong documentation, active community, and abundance of tutorials and courses make it accessible to learners. By understanding Node.js, students can grasp fundamental concepts of server-side programming, event-driven architecture, asynchronous coding, and modern web development practices. Learning Node.js also opens opportunities in areas such as web development, mobile backend services, cloud computing, and microservices architecture.
In conclusion, Node.js has transformed the landscape of web development by bringing JavaScript to the server side and enabling developers to build fast, scalable, and real-time applications. Its event-driven, non-blocking architecture makes it ideal for I/O-intensive tasks, while npm provides a rich ecosystem of modules for rapid development. Node.js supports full-stack JavaScript development, encourages modular and maintainable code, and is used by leading companies worldwide. Despite some challenges in CPU-intensive tasks, Node.js continues to evolve and remain relevant in modern web development. For anyone looking to enter the world of backend programming or build full-stack applications, Node.js is not just a valuable tool—it is an essential skill.
Answer:
Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript engine. It allows you to run JavaScript code on the server side. Node.js is event-driven, non-blocking, and asynchronous, which makes it efficient for building scalable applications, especially for I/O-heavy operations like APIs, real-time chats, or streaming services.
Key Features:
Single-threaded but highly scalable
Asynchronous and non-blocking I/O
Uses the V8 engine for fast execution
NPM (Node Package Manager) for managing packages
Answer:
Asynchronous & Event-Driven: All APIs of Node.js are asynchronous, meaning they don’t block execution.
Single-Threaded: Uses a single thread with an event loop to handle multiple requests.
High Performance: Built on the V8 engine, which compiles JavaScript into native machine code.
Cross-Platform: Runs on Windows, Linux, macOS.
NPM: Node.js comes with a package manager (NPM) to manage libraries and dependencies.
No Buffering: Node.js applications output data in chunks.
| Feature | JavaScript | Node.js |
|---|---|---|
| Environment | Runs in the browser | Runs on server (outside browser) |
| Purpose | Client-side scripting | Server-side scripting |
| APIs | Browser APIs (DOM, BOM) | Server APIs (HTTP, File System) |
| Usage | Web page interactivity | Backend services, APIs, real-time apps |
Answer:
Node.js uses events to handle asynchronous operations. When an operation is done, it triggers an event that executes a callback function.
Example:
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
eventEmitter.on('sayHello', () => {
console.log('Hello, Node.js!');
});
eventEmitter.emit('sayHello'); // Output: Hello, Node.js!
Here, on listens to an event, and emit triggers it.
Answer:
| Feature | Synchronous | Asynchronous |
|---|---|---|
| Blocking | Yes, blocks execution | No, non-blocking |
| Execution | One task at a time | Multiple tasks can run |
| Example | fs.readFileSync('file.txt') |
fs.readFile('file.txt', callback) |
Answer:
The Event Loop allows Node.js to perform non-blocking I/O operations even though JavaScript is single-threaded. It constantly checks the callback queue and executes tasks when the main thread is free.
Simplified Flow:
Node executes synchronous code.
Async operations are sent to the system kernel or event queue.
When done, the callback is pushed to the queue.
Event loop executes the callback.
Answer:
NPM (Node Package Manager) is used to install, manage, and share Node.js packages.
Example commands:
npm init – Create a new project with package.json
npm install express – Install Express.js package
npm uninstall package-name – Remove a package
require() and import in Node.js?Answer:
require() is used in CommonJS modules (older Node.js style).
import is used in ES6 modules (modern JavaScript).
Example:
// CommonJS
const fs = require('fs');
// ES6
import fs from 'fs';
Answer:
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello, Node.js!');
});
server.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Answer:
Middleware functions are functions that execute during the request-response cycle. They can modify request/response objects, end the request-response cycle, or call next middleware.
Example:
const express = require('express');
const app = express();
app.use((req, res, next) => {
console.log('Request URL:', req.url);
next();
});
app.get('/', (req, res) => {
res.send('Hello, Middleware!');
});
app.listen(3000);
process.nextTick(), setImmediate(), and setTimeout() in Node.js?process.nextTick() → Executes callback before the next event loop.
setImmediate() → Executes callback after the current poll phase.
setTimeout(callback, 0) → Executes callback after at least 0ms, scheduled in timers phase.
Answer:
Node.js uses callback patterns and try-catch for errors in synchronous code and Promises/async-await for asynchronous code.
Callback example:
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log(data);
});
Async/Await example:
const fs = require('fs').promises;
async function readFile() {
try {
const data = await fs.readFile('file.txt', 'utf8');
console.log(data);
} catch (err) {
console.error('Error:', err);
}
}
readFile();
Answer:
Streams allow reading or writing data in chunks, which is memory-efficient. Types of streams:
Readable – Read data (fs.createReadStream())
Writable – Write data (fs.createWriteStream())
Duplex – Read & write
Transform – Modify data while reading/writing
readFile and createReadStream?| Feature | readFile | createReadStream |
|---|---|---|
| Memory | Loads entire file | Reads in chunks |
| Use case | Small files | Large files |
| Async | Callback-based | Event-based (data, end) |
Answer:
You use database drivers or ORMs. Example with MongoDB:
const { MongoClient } = require('mongodb');
const url = 'mongodb://localhost:27017';
const client = new MongoClient(url);
async function run() {
try {
await client.connect();
console.log('Connected to MongoDB');
const db = client.db('testdb');
const collection = db.collection('users');
const user = await collection.findOne({ name: 'John' });
console.log(user);
} finally {
await client.close();
}
}
run();
Perfect! Let’s dive into Part 2: 30+ Node.js Questions & Answers for Freshers. I’ll focus on deeper topics, tricky concepts, and interview-style questions. I’ll also explain answers clearly so you can remember them easily.
Answer:
Node.js is non-blocking, event-driven, and asynchronous, whereas PHP is usually blocking and synchronous.
Node.js uses JavaScript on the server side; PHP has its own syntax.
Node.js is better for real-time apps (chat, streaming), while PHP is great for request-response websites.
Answer:
Node.js is a runtime environment for executing JavaScript.
Express.js is a framework built on top of Node.js to simplify server creation, routing, and middleware handling.
package.json file.Answer:
Holds project metadata: name, version, description, author.
Lists dependencies and devDependencies.
Scripts section allows running commands like npm start or npm test.
process.env and dotenv?Answer:
process.env stores environment variables provided by the system.
dotenv is a Node.js package that loads environment variables from a .env file into process.env.
exports and module.exports?Answer:
exports is a shorthand reference to module.exports.
Only module.exports is returned by require().
If you reassign exports directly, it won’t work.
Example:
// Correct
module.exports = { foo: 'bar' };
// Incorrect
exports = { foo: 'bar' }; // won't work
Answer:
A callback is a function passed as an argument to another function to execute after a task is done.
Example:
function greet(name, callback) {
console.log(`Hello, ${name}`);
callback();
}
greet('John', () => console.log('Greeting done'));
Answer:
A Promise is an object representing future completion or failure of an asynchronous operation.
States: pending → fulfilled → rejected
Example:
const promise = new Promise((resolve, reject) => {
let success = true;
success ? resolve('Done') : reject('Error');
});
promise.then(console.log).catch(console.error);
Answer:
Async marks a function to return a Promise.
Await waits for a Promise to resolve before moving on.
Makes asynchronous code look synchronous.
Example:
async function fetchData() {
try {
const data = await fetch('https://api.example.com');
console.log(await data.json());
} catch (err) {
console.error(err);
}
}
fs.readFile and fs.readFileSync?fs.readFile → asynchronous, non-blocking
fs.readFileSync → synchronous, blocking
Answer:
REPL = Read-Eval-Print Loop
Allows running Node.js commands line by line in the terminal.
Useful for testing small pieces of code.
Answer:
Buffer is a temporary storage for binary data.
Useful when working with streams or reading files.
Example:
const buffer = Buffer.from('Hello');
console.log(buffer.toString()); // Output: Hello
spawn() and fork() in Node.js child processes?spawn() → Launches a new process without Node.js features, good for shell commands.
fork() → Special case of spawn to create a new Node.js process with IPC (inter-process communication).
Node.js uses V8’s garbage collector.
Automatically frees memory for objects no longer referenced.
Developers need to avoid memory leaks in long-running applications.
setImmediate() and process.nextTick()?process.nextTick() → Executes before next event loop iteration
setImmediate() → Executes on the next iteration of the event loop
Answer:
Modules are self-contained files that encapsulate code.
Node.js has built-in modules (fs, http) and custom modules.
Use require() or import to include them.
| Feature | CommonJS | ES Modules |
|---|---|---|
| Syntax | require() |
import/export |
| Loading | Synchronous | Asynchronous |
| Default in Node | Yes | Optional (.mjs) |
process.exit() and process.kill()?process.exit() → Ends current Node.js process immediately
process.kill(pid) → Sends a signal to terminate another process
Answer:
Node.js runs on single-thread by default.
Cluster module allows spawning child processes to use all CPU cores, improving performance.
event loop phases in Node.js?Answer:
Timers → setTimeout and setInterval
Pending callbacks → Execute I/O callbacks deferred
Idle/prepare → Internal
Poll → Retrieve new I/O events
Check → setImmediate callbacks
Close callbacks → e.g., socket closed
Operational errors – I/O failures, network errors
Programmer errors – Bugs, undefined variables
require() and require.resolve()?require() → Loads a module
require.resolve() → Returns resolved path of module
npm and yarn?Both are package managers
Yarn is faster, uses lock files for consistent installs
NPM comes built-in with Node.js
Use console.log()
Use Node Inspector: node --inspect index.js
Use VS Code Debugger for breakpoints
process.nextTick() and Promise.resolve().then()?process.nextTick() → Executes before Promise microtasks
Promise.resolve().then() → Executes after current operation, before next event loop tick
Backtick strings (```) for multi-line strings and interpolation
Example:
const name = 'John';
console.log(`Hello, ${name}`); // Hello, John
res.send() and res.json() in Express.js?res.send() → Sends text, HTML, or JSON
res.json() → Sends JSON only and sets Content-Type: application/json
Use middleware like multer
Example:
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('file'), (req, res) => {
res.send('File uploaded');
});
npm shrinkwrap?Locks exact versions of dependencies to ensure consistency across environments.
Use Promises
Use async/await
Break code into smaller functions
app.listen() and server.listen()?app.listen() → Express shortcut
server.listen() → Node.js HTTP server method
require.cache and fresh require()?Node.js caches required modules in require.cache
Reloading the same module uses cache unless manually cleared
Use helmet for headers
Validate input to prevent injections
Use HTTPS and JWT for authentication
Answer:
Node.js is single-threaded with an event loop; traditional servers use multi-threading.
Node.js handles concurrent requests efficiently using non-blocking I/O without creating a thread for each request.
Best for I/O-heavy applications, while multi-threaded servers are better for CPU-heavy tasks.
Answer:
Clustering – Use all CPU cores (cluster module).
Load Balancing – Distribute traffic across multiple instances using NGINX or PM2.
Microservices architecture – Split a monolithic app into smaller services.
Horizontal scaling – Deploy multiple servers.
Answer:
Node.js is single-threaded, so heavy CPU tasks can block the event loop.
Solutions:
Offload tasks to child processes (child_process.fork())
Use worker threads (worker_threads module)
Move processing to a separate microservice
Answer:
Allows running JavaScript in parallel threads.
Useful for CPU-bound tasks.
Example:
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js');
worker.on('message', msg => console.log(msg));
worker.postMessage('Start');
setTimeout() – Execute after a delay
setInterval() – Execute repeatedly at intervals
setImmediate() – Execute on the next event loop iteration
process.nextTick() – Execute before the next event loop tick
Answer:
Detection:
Use Node.js profiler, Chrome DevTools, or heap snapshots.
Monitor memory usage with process.memoryUsage().
Prevention:
Avoid global variables for large data
Remove event listeners when not needed
Close streams, DB connections properly
Node.js is single-threaded, but concurrency is achieved via:
Event Loop – Handles I/O without blocking
Asynchronous callbacks/promises – Multiple tasks can run simultaneously
Worker threads/child processes – For CPU-bound tasks
| Feature | HTTP | WebSocket |
|---|---|---|
| Connection | Request-response | Persistent, full-duplex |
| Use case | APIs, web pages | Real-time apps (chat, gaming) |
| Overhead | Higher (new request each time) | Lower (single connection) |
Example of WebSocket in Node.js:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
ws.on('message', message => console.log(`Received: ${message}`));
ws.send('Hello Client');
});
Streams allow reading/writing data in chunks instead of loading it all into memory.
Types: Readable, Writable, Duplex, Transform
Example:
const fs = require('fs');
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');
readStream.pipe(writeStream); // Efficiently copies file
Techniques:
Use asynchronous code
Use streams for large data
Cache frequently used data (Redis)
Avoid blocking the event loop
Use cluster module for multi-core servers
Optimize database queries
process.nextTick() and setImmediate() in real-time scenarios?process.nextTick() → Executes before I/O events; can starve the event loop if abused
setImmediate() → Executes after I/O events; safer for heavy tasks
Use callbacks: Check err parameter
Use Promises: .catch()
Use async/await with try/catch
Use process.on('uncaughtException') as a last resort (not recommended for production)
Answer:
User logs in → server generates JWT token
Token sent to client
Client sends token in headers for protected routes
Server verifies token with secret
Example with Express:
const jwt = require('jsonwebtoken');
const token = jwt.sign({ userId: 123 }, 'secretKey', { expiresIn: '1h' });
jwt.verify(token, 'secretKey', (err, decoded) => {
if(err) return console.error('Invalid token');
console.log(decoded.userId);
});
process.on('exit') and process.on('beforeExit')?beforeExit → Fires before Node.js exits when event loop is empty
exit → Fires when Node.js is about to exit, cannot schedule async tasks
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if(cluster.isMaster){
for(let i=0; i<numCPUs; i++){
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died`);
});
} else {
http.createServer((req, res) => {
res.end('Hello from worker');
}).listen(3000);
}
PM2 = Process Manager for Node.js
Features:
Auto restart crashed apps
Cluster mode
Logs management
Monitoring CPU/memory usage
Avoid synchronous code (readFileSync) in production
Use streams for large files
Offload heavy computations to worker threads
Use middleware like express-rate-limit
Prevents DoS attacks and abuse
Example:
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({ windowMs: 15*60*1000, max: 100 });
app.use(limiter);
Break a monolithic app into smaller, independent services
Each service runs its own Node.js instance and communicates via HTTP, gRPC, or message queues
Use WebSockets (socket.io)
Can also use Server-Sent Events (SSE) for unidirectional streaming
Example (Socket.io):
const io = require('socket.io')(3000);
io.on('connection', socket => {
socket.emit('welcome', 'Hello!');
});
Use dotenv: .env file
Access via process.env.VAR_NAME
cluster and worker_threads?| Feature | Cluster | Worker Threads |
|---|---|---|
| Multi-core | Yes, forks processes | Yes, runs threads |
| Memory | Separate memory per process | Shared memory |
| Use case | Scale server | CPU-heavy tasks |
Use Promises and async/await
Break code into small modular functions
Use control flow libraries (optional)
Use asynchronous code
Handle uncaught exceptions
Implement logging (Winston/Log4js)
Use PM2 or Docker for deployment
Optimize database queries
Use HTTPS and Helmet for security
Tools: PM2, New Relic, AppDynamics, Prometheus + Grafana
Monitor CPU, memory, response times, errors
Use in-memory caching (node-cache) for small data
Use Redis for distributed caching
Reduces DB load and improves performance
const fs = require('fs');
const http = require('http');
http.createServer((req, res) => {
const stream = fs.createReadStream('largefile.txt');
stream.pipe(res);
}).listen(3000);
Use express-session
Store sessions in memory, Redis, or database
Example:
const session = require('express-session');
app.use(session({ secret: 'secret', resave: false, saveUninitialized: true }));
Sanitize user input
Use Helmet for secure headers
Implement rate-limiting
Use HTTPS
Store passwords with bcrypt
Use Socket.io
Server listens for messages → broadcasts to other clients
Maintain user connections and rooms
Answer:
Node.js is single-threaded and event-driven.
Uses V8 engine to execute JavaScript.
Libuv library provides thread pool and event loop for I/O operations.
Asynchronous operations are queued and executed via callback functions.
Flow:
Request → Event Loop → Callback Queue → Execution
| Feature | Synchronous | Asynchronous |
|---|---|---|
| Execution | Blocks the thread | Non-blocking |
| Example | fs.readFileSync() |
fs.readFile() |
| Performance | Slower for I/O | High-performance |
Answer:
The event loop manages callbacks in Node.js:
Phases:
Timers – setTimeout, setInterval
I/O callbacks – Completed async operations
Idle, prepare – Internal tasks
Poll – Fetch new events
Check – setImmediate callbacks
Close callbacks – Cleanup
Node.js executes one event at a time, enabling non-blocking I/O.
Answer:
Streams allow processing data piece by piece, useful for large files.
Types:
Readable – Read data (fs.createReadStream())
Writable – Write data (fs.createWriteStream())
Duplex – Read & write
Transform – Modify data while streaming
Example:
const fs = require('fs');
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');
readStream.pipe(writeStream);
process.nextTick() and setImmediate()| Feature | process.nextTick() | setImmediate() |
|---|---|---|
| Execution timing | Before I/O | After I/O |
| Priority | High | Lower |
| Use case | Next iteration in same phase | Post I/O callbacks |
Answer:
Node.js runs in a single thread, but cluster allows multiple workers to handle requests.
Utilizes multi-core CPUs.
const cluster = require('cluster');
const http = require('http');
if (cluster.isMaster) {
cluster.fork();
cluster.fork();
} else {
http.createServer((req, res) => res.end("Hello")).listen(3000);
}
| Feature | spawn() | fork() |
|---|---|---|
| Launches process | Any command | Node.js script |
| IPC (Inter-process communication) | β | β |
| Returns | ChildProcess stream | ChildProcess object with communication |
Answer:
Buffer stores raw binary data temporarily.
Useful for streams, TCP, and file operations.
const buf = Buffer.from('Hello Node');
console.log(buf.toString()); // Hello Node
Use error-first callbacks:
fs.readFile('file.txt', (err, data) => {
if (err) return console.error(err);
console.log(data);
});
Use try-catch for synchronous code.
Use process.on('uncaughtException') for global exceptions (last resort).
Answer:
Middleware functions execute during request-response cycle.
Can modify request/response objects or end the response.
app.use((req, res, next) => {
console.log('Middleware executed');
next(); // pass control to next middleware
});
Callbacks → Basic async handling
Promises → Cleaner syntax for async operations
async/await → Syntactic sugar for promises
const fs = require('fs').promises;
async function readFile() {
const data = await fs.readFile('file.txt', 'utf8');
console.log(data);
}
readFile();
| Feature | process.nextTick() | setTimeout() |
|---|---|---|
| Execution | Next iteration of same phase | Timer phase after delay |
| Priority | Higher | Lower |
| Use case | Callbacks after current operation | Delayed execution |
Answer:
EventEmitter is a core Node.js module.
Enables publish-subscribe pattern.
const EventEmitter = require('events');
const emitter = new EventEmitter();
emitter.on('event', msg => console.log(msg));
emitter.emit('event', 'Hello EventEmitter');
require and import| Feature | require() | import |
|---|---|---|
| Syntax | CommonJS | ES6 modules |
| Runtime | Synchronous | Static |
| Support | Node.js | Modern Node & bundlers |
Use cluster module for multi-core
Avoid blocking code (no heavy synchronous operations)
Cache database queries
Use streams for large files
Proper error handling
setImmediate() and process.nextTick()nextTick → executes before I/O
setImmediate → executes after I/O callbacks
Both are used to schedule tasks in Node.js event loop.
Use streams to process chunks.
Avoid loading entire file in memory.
Example using Express:
const fs = require('fs');
app.post('/upload', (req, res) => {
const writeStream = fs.createWriteStream('file.txt');
req.pipe(writeStream);
req.on('end', () => res.send('File uploaded'));
});
| Feature | Node.js | Traditional servers |
|---|---|---|
| I/O | Non-blocking | Blocking |
| Threading | Single-threaded | Multi-threaded |
| Performance | High concurrency | Heavy thread per request |
| Language | JavaScript | PHP, Java, etc |
| Feature | Buffer | Stream |
|---|---|---|
| Data | Holds entire data | Data in chunks |
| Memory | Higher usage | Low memory usage |
| Use case | Small files | Large files & network data |
Avoid eval() and dynamic code execution
Validate user inputs
Use HTTPS
Sanitize database queries to prevent injection
Keep dependencies updated
Answer:
Node.js is single-threaded, event-driven, non-blocking I/O.
Core components:
V8 engine → Executes JavaScript
Libuv → Handles async I/O, thread pool, and event loop
Event loop → Manages callback execution
Execution flow:
Request → Event Loop → Callback Queue → Execution
All I/O operations are executed asynchronously using callbacks, promises, or async/await.
| Feature | Node.js | Traditional Servers (e.g., Apache) |
|---|---|---|
| Threading | Single-threaded | Multi-threaded |
| I/O | Non-blocking | Blocking |
| Performance | High concurrency | Each request requires a new thread |
| Language | JavaScript | PHP/Java/Other |
| Scaling | Cluster module | Multiple processes or load balancer |
Answer:
The event loop is central to Node.js async execution:
Phases of event loop:
Timers → Executes callbacks of setTimeout and setInterval
I/O callbacks → Executes callbacks of completed I/O operations
Idle, prepare → Internal tasks
Poll → Fetches new I/O events
Check → Executes setImmediate() callbacks
Close callbacks → Handles cleanup of closed events
Node.js executes one callback at a time, ensuring non-blocking I/O without multi-threading.
Answer:
Streams allow processing data in chunks, instead of loading the entire data in memory. Useful for large files or network data.
Types of streams:
Readable – e.g., fs.createReadStream()
Writable – e.g., fs.createWriteStream()
Duplex – Read & write (e.g., TCP sockets)
Transform – Modify data while streaming (e.g., zlib compression)
Example:
const fs = require('fs');
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');
readStream.pipe(writeStream);
process.nextTick() and setImmediate()| Feature | process.nextTick() | setImmediate() |
|---|---|---|
| Execution timing | Before I/O callbacks | After I/O callbacks |
| Priority | Higher | Lower |
| Use case | Execute code after current operation | Execute code after current event loop iteration |
Answer:
Node.js is single-threaded, so clustering allows multiple worker processes to handle requests.
Utilizes multi-core CPUs, improving scalability and performance.
Example:
const cluster = require('cluster');
const http = require('http');
if(cluster.isMaster){
for(let i=0;i<4;i++){
cluster.fork();
}
} else {
http.createServer((req,res)=>{
res.end('Hello from worker ' + process.pid);
}).listen(3000);
}
spawn() and fork() in Node.js| Feature | spawn() | fork() |
|---|---|---|
| Launches process | Any command-line task | Node.js scripts |
| Inter-process communication (IPC) | β | β |
| Returns | ChildProcess streams | ChildProcess with communication channels |
Answer:
Buffer is used to handle raw binary data.
Crucial for file streams, TCP sockets, or HTTP responses.
const buf = Buffer.from('Hello Node');
console.log(buf.toString()); // Hello Node
Node.js uses EventEmitter for publish-subscribe pattern.
Applications respond to events without blocking.
const EventEmitter = require('events');
const emitter = new EventEmitter();
emitter.on('dataReceived', msg => console.log(msg));
emitter.emit('dataReceived', 'Hello Events!');
require and import| Feature | require() | import |
|---|---|---|
| Syntax | CommonJS | ES6 modules |
| Execution | Runtime | Static, compile-time |
| Use case | Node.js modules | Modern ES6+ modules |
| Async support | β | β
(with dynamic import()) |
Callbacks – Old style async handling
Promises – Cleaner syntax for async
async/await – Syntactic sugar over promises
Example using async/await:
const fs = require('fs').promises;
async function readFile() {
const data = await fs.readFile('file.txt', 'utf8');
console.log(data);
}
readFile();
Use error-first callbacks:
fs.readFile('file.txt', (err, data) => {
if(err) return console.error(err);
console.log(data);
});
Use try-catch for synchronous code.
Use process.on('uncaughtException') for global exception handling (not recommended for production).
Avoid blocking code (no heavy synchronous operations)
Use cluster module for multi-core scaling
Stream large files instead of loading them in memory
Cache database queries or API responses
Minimize DOM or network operations in server-side rendering
Validate all user inputs
Avoid eval() or dynamic code execution
Use HTTPS
Sanitize database queries (prevent SQL/NoSQL injection)
Keep Node.js and npm packages updated
Use streams to process files chunk by chunk
Avoid storing full file in memory
Example with Express.js:
const fs = require('fs');
app.post('/upload', (req, res) => {
const writeStream = fs.createWriteStream('file.txt');
req.pipe(writeStream);
req.on('end', () => res.send('File uploaded'));
});
| Feature | Synchronous | Asynchronous |
|---|---|---|
| Execution | Blocks event loop | Non-blocking |
| Example | fs.readFileSync() |
fs.readFile() |
| Use case | Small tasks, scripts | High-performance servers |
Uses V8 garbage collector
Avoid memory leaks by cleaning:
Event listeners with .off()
Detached DOM elements
Unused buffers
Single-threaded event loop handles multiple concurrent connections
Non-blocking I/O allows Node.js to serve thousands of clients
Clustering or worker threads can utilize multi-core CPUs
setImmediate() and setTimeout()| Feature | setImmediate() | setTimeout(fn, 0) |
|---|---|---|
| Execution | Next event loop iteration | After 0ms delay |
| Priority | Higher for I/O tasks | Timer phase |
| Use case | Post I/O callbacks | Delayed execution |
Web servers – Express, Koa
Real-time apps – Chat apps using Socket.io
Streaming platforms – Video/audio streaming
API servers – REST & GraphQL
IoT apps – Device communication