Node.js Interview Questions & Answers (2026) – RankWeb3
const http = require('http');
const port = 3000;

const server = http.createServer(
(req, res) => {
res.writeHead(200);
res.end('Hello Node!');
}
);

server.listen(port);
// Server running βœ“
RankWeb3β€ΊInterview Questionsβ€ΊNode.js
🟒 Node.js All Levels 30 Questions Updated 2026

Node.js Interview
Questions & Answers

πŸ“… Updated: March 2026
⏱️ Read time: ~22 min
🎯 30 questions β€” Beginner to Advanced
✍️ By RankWeb3 Team
30
Total Questions
10
Beginner
11
Intermediate
9
Advanced

🌱Beginner QuestionsQ1–Q10

1
What is Node.js and why was it created?
BeginnerVery Common
+

Node.js is a JavaScript runtime built on Chrome's V8 engine that lets you run JavaScript on the server β€” outside the browser. Created by Ryan Dahl in 2009, it was built to solve a problem: traditional web servers like Apache blocked the thread while waiting for I/O (file reads, DB queries), wasting CPU cycles.

  • Non-blocking I/O: Node uses an event-driven, asynchronous model β€” it doesn't wait for slow operations to finish before handling the next request.
  • Single language: JavaScript on both front-end and back-end β€” same team, shared code.
  • npm ecosystem: Over 2 million packages β€” the largest package registry in the world.
  • Great for: Real-time apps (chat, live updates), REST APIs, microservices, CLI tools, BFF (Backend For Frontend).
  • Not great for: CPU-heavy computation (image processing, video encoding, machine learning).
πŸ’‘Why interviewers ask this: To check you understand Node's design philosophy β€” not just that it runs JavaScript. Mentioning "non-blocking I/O" and the event loop shows real understanding.
2
What is the Node.js Event Loop?
BeginnerVery Common
+

The event loop is the core mechanism that makes Node.js asynchronous and non-blocking. Node is single-threaded β€” it can only do one thing at a time β€” but the event loop lets it handle many operations concurrently by delegating I/O to the OS and processing results when they're ready.

Node.js β€” Event Loop Order
// Event loop phases (simplified): // 1. timers β€” setTimeout, setInterval callbacks // 2. pending β€” I/O callbacks deferred from previous iteration // 3. idle/prepare β€” internal use // 4. poll β€” retrieve new I/O events (blocks here if nothing else) // 5. check β€” setImmediate callbacks // 6. close β€” close event callbacks // Between each phase: microtasks (Promises, process.nextTick) // process.nextTick fires BEFORE promises in microtask queue console.log('1'); // sync setTimeout(() => console.log('2'), 0); // timers phase setImmediate(() => console.log('3')); // check phase process.nextTick(() => console.log('4')); // microtask (before promises) Promise.resolve().then(() => console.log('5')); // microtask console.log('6'); // sync // Output: 1 β†’ 6 β†’ 4 β†’ 5 β†’ 2 β†’ 3
πŸ’‘Key insight: process.nextTick fires before any I/O or timers β€” even before Promise callbacks. This makes it useful for scheduling something at the very end of the current operation, before anything else asynchronous runs.
3
What is the difference between CommonJS (require) and ES Modules (import)?
BeginnerVery Common
+
FeatureCommonJS (CJS)ES Modules (ESM)
Syntaxrequire() / module.exportsimport / export
LoadingSynchronousAsynchronous (static analysis)
Tree-shaking❌ Not supportedβœ… Supported by bundlers
Top-level await❌ Noβœ… Yes
File extension.js or .cjs.mjs or "type":"module" in package.json
Default in Nodeβœ… Traditional defaultOpt-in (Node 12+, stable Node 14+)
Node.js
// CommonJS (most legacy Node code): const fs = require('fs'); const myUtil = require('./utils'); module.exports = { greet }; // ES Modules (modern Node / TypeScript): import fs from 'fs'; import { helper } from './utils.js'; export default function greet() {} export { helper };
4
What is npm and what are the key commands?
BeginnerVery Common
+

npm (Node Package Manager) is the default package manager for Node.js. It manages dependencies, scripts, and publishes packages to the npm registry.

Bash β€” npm Commands
# Initialise project: npm init -y # Install dependency: npm install express # adds to "dependencies" npm install jest --save-dev # adds to "devDependencies" npm install -g nodemon # global install # Install all dependencies from package.json: npm install # Remove package: npm uninstall express # Run script (defined in package.json): npm run dev npm test # Check for outdated packages: npm outdated # Audit for security vulnerabilities: npm audit npm audit fix # Lock file (never delete this!): # package-lock.json β€” exact versions for reproducible installs
πŸ’‘dependencies vs devDependencies: dependencies are needed at runtime (express, mongoose). devDependencies are only needed during development (jest, eslint, typescript). When deploying, you can run npm install --production to skip devDependencies.
5
What are Node.js built-in core modules?
BeginnerCommon
+

Node.js ships with built-in modules that you can require without installing anything. They cover file system, networking, paths, cryptography, and more.

Node.js β€” Core Modules
const fs = require('fs'); // file system const path = require('path'); // file paths const http = require('http'); // HTTP server/client const https = require('https'); // HTTPS const os = require('os'); // operating system info const events = require('events'); // EventEmitter const stream = require('stream'); // streams const crypto = require('crypto'); // hashing, encryption const buffer = require('buffer'); // binary data const util = require('util'); // promisify, inspect, etc. const url = require('url'); // URL parsing const child_p = require('child_process'); // spawn subprocesses const cluster = require('cluster'); // multi-core workers // Common usage β€” join paths safely: const filePath = path.join(__dirname, 'data', 'users.json');
6
What is the difference between synchronous and asynchronous file reading in Node.js?
BeginnerVery Common
+
Node.js
const fs = require('fs'); // ❌ Synchronous β€” BLOCKS the event loop: const data = fs.readFileSync('file.txt', 'utf8'); console.log(data); // ok for scripts, terrible for servers // βœ… Asynchronous callback β€” non-blocking: fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); }); console.log('This prints FIRST'); // event loop not blocked // βœ… Promise-based (modern, preferred): const { promises: fsPromises } = require('fs'); async function readFile() { const data = await fsPromises.readFile('file.txt', 'utf8'); console.log(data); }
⚠️Never use sync methods in a server handler! fs.readFileSync in an HTTP handler blocks ALL requests while it runs. One slow file read can freeze your entire server.
7
What is Express.js and what problem does it solve?
BeginnerVery Common
+

Express.js is a minimal, unopinionated web framework for Node.js. Node's built-in http module is powerful but low-level β€” you'd have to manually parse routes, bodies, cookies, and handle errors. Express wraps all of this into a clean, simple API.

Node.js β€” Express Basics
const express = require('express'); const app = express(); // Built-in middleware: app.use(express.json()); // parse JSON bodies app.use(express.urlencoded({ extended: true })); // Routes: app.get('/', (req, res) => { res.json({ message: 'Hello from RankWeb3!' }); }); app.post('/users', async (req, res) => { const { name, email } = req.body; const user = await User.create({ name, email }); res.status(201).json(user); }); app.listen(3000, () => console.log('Server running on :3000'));
8
What are environment variables and how do you use them in Node.js?
BeginnerVery Common
+

Environment variables are key-value pairs stored outside your code β€” used for configuration that changes between environments (dev, staging, production) or that must be kept secret (API keys, DB passwords).

Node.js
// .env file (never commit this!): // PORT=3000 // DB_URL=mongodb://localhost:27017/mydb // JWT_SECRET=supersecretkey123 // NODE_ENV=development // Load .env with dotenv package: require('dotenv').config(); // Access environment variables: const port = process.env.PORT || 3000; const dbUrl = process.env.DB_URL; const isProd = process.env.NODE_ENV === 'production'; // Validate required env vars on startup: const required = ['DB_URL', 'JWT_SECRET']; required.forEach(key => { if (!process.env[key]) { throw new Error(`Missing required env var: ${key}`); } });
⚠️Always add .env to .gitignore. Committing secrets to a public repository is one of the most common and dangerous developer mistakes. Once pushed, assume the secret is compromised.
9
What is callback hell and how do you avoid it?
BeginnerVery Common
+

Callback hell (also called "the pyramid of doom") is when nested callbacks become so deeply indented that the code is hard to read, debug, and maintain.

Node.js
// ❌ Callback hell: fs.readFile('users.json', (err, data) => { if (err) return console.error(err); db.connect((err, conn) => { if (err) return console.error(err); conn.query('SELECT ...', (err, rows) => { if (err) return console.error(err); sendEmail(rows, (err) => { // getting worse... if (err) return console.error(err); }); }); }); }); // βœ… Async/await (flat, readable): async function processUsers() { try { const data = await fsPromises.readFile('users.json'); const conn = await db.connect(); const rows = await conn.query('SELECT ...'); await sendEmail(rows); } catch (err) { console.error(err); // one place for all errors } }
10
What is __dirname and __filename in Node.js?
Beginner
+

These are global variables available in every CommonJS module (not ESM):

Node.js
// __dirname β€” absolute path of the DIRECTORY containing this file // __filename β€” absolute path of THIS FILE console.log(__dirname); // /home/meraj/project/src console.log(__filename); // /home/meraj/project/src/app.js // Why useful: build paths that work on any machine: const dbPath = path.join(__dirname, '../data/db.json'); // In ES Modules (__dirname not available, use this instead): import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename);

⚑Intermediate QuestionsQ11–Q21

11
What is middleware in Express.js and how does it work?
IntermediateVery Common
+

Middleware are functions that have access to the request, response, and next objects. They execute in sequence and form a pipeline β€” each middleware either ends the request or calls next() to pass control to the next function.

Node.js β€” Express Middleware
// Middleware signature: (req, res, next) // 1. Application-level middleware (runs on all routes): app.use((req, res, next) => { console.log(`${req.method} ${req.url} ${new Date()}`); next(); // pass control to next middleware }); // 2. Authentication middleware: function authGuard(req, res, next) { const token = req.headers.authorization; if (!token) return res.status(401).json({ error: 'Unauthorised' }); req.user = verifyToken(token); next(); } // 3. Route-level middleware: app.get('/admin', authGuard, (req, res) => { res.json({ user: req.user }); }); // 4. Error-handling middleware (4 parameters!): app.use((err, req, res, next) => { console.error(err.stack); res.status(err.status || 500).json({ error: err.message }); });
πŸ’‘Order matters! Middleware executes in the order it's registered with app.use(). Your error handler must be registered LAST (after all routes) and must have exactly 4 parameters to be recognised as an error handler.
12
What are Node.js Streams and why are they useful?
IntermediateVery Common
+

Streams are objects that let you read or write data in chunks rather than loading everything into memory at once. They're memory-efficient for handling large files, real-time data, or piping between sources.

Node.js
const fs = require('fs'); // ❌ Without streams β€” loads ENTIRE file into memory: const data = fs.readFileSync('huge-file.csv'); // ← 5GB file = crash! // βœ… With streams β€” processes in small chunks: const readable = fs.createReadStream('huge-file.csv'); const writable = fs.createWriteStream('output.csv'); readable.pipe(writable); // pipe: connect readable β†’ writable // 4 types of streams: // Readable β€” data you can read (fs.createReadStream, http.IncomingMessage) // Writable β€” data you can write (fs.createWriteStream, http.ServerResponse) // Duplex β€” both readable and writable (net.Socket) // Transform β€” modify data while reading/writing (zlib, crypto) // Compress file with transform stream: const zlib = require('zlib'); fs.createReadStream('file.txt') .pipe(zlib.createGzip()) .pipe(fs.createWriteStream('file.txt.gz'));
13
What is the EventEmitter in Node.js?
IntermediateCommon
+

EventEmitter is Node's implementation of the observer/pub-sub pattern. Objects extend EventEmitter to emit named events, and listeners can subscribe to those events. It's the foundation of Node's streaming and networking APIs.

Node.js
const { EventEmitter } = require('events'); // Create a custom event emitter: class OrderSystem extends EventEmitter {} const orders = new OrderSystem(); // Subscribe to events: orders.on('order:placed', (order) => { console.log(`New order: ${order.id}`); }); orders.once('order:placed', () => { // fires only ONCE, then automatically removes listener }); // Emit event with payload: orders.emit('order:placed', { id: 'ORD-001', total: 99.99 }); // Remove listener: const handler = () => {}; orders.on('order:placed', handler); orders.off('order:placed', handler); // removeListener // Prevent memory leak warning (default max: 10 listeners): orders.setMaxListeners(20);
14
How do you build a REST API with Express? What are REST principles?
IntermediateVery Common
+

REST (Representational State Transfer) is an architectural style for APIs. Key principles: stateless, client-server, uniform interface using HTTP methods, resource-based URLs.

Node.js β€” RESTful Express API
const router = express.Router(); // GET /users β†’ list all users // GET /users/:id β†’ get one user // POST /users β†’ create user // PUT /users/:id β†’ replace user (full update) // PATCH /users/:id β†’ partial update // DELETE /users/:id β†’ delete user router.get('/', async (req, res) => { const { page = 1, limit = 10, sort = 'name' } = req.query; const users = await User.find().limit(+limit).skip((+page-1)*+limit); res.json({ data: users, page: +page, limit: +limit }); }); router.get('/:id', async (req, res, next) => { const user = await User.findById(req.params.id); if (!user) return res.status(404).json({ error: 'Not found' }); res.json(user); }); router.post('/', async (req, res, next) => { try { const user = await User.create(req.body); res.status(201).json(user); } catch (err) { next(err); } // pass to error handler }); app.use('/api/users', router);
15
What is JWT authentication and how do you implement it in Node.js?
IntermediateVery Common
+

JWT (JSON Web Token) is a compact, self-contained way to transmit authentication data. A JWT has three parts: Header.Payload.Signature β€” base64url encoded and signed with a secret key.

Node.js β€” JWT Auth
const jwt = require('jsonwebtoken'); const bcrypt = require('bcrypt'); // Login route β€” issue a token: app.post('/login', async (req, res) => { const { email, password } = req.body; const user = await User.findOne({ email }); if (!user) return res.status(401).json({ error: 'Invalid credentials' }); const valid = await bcrypt.compare(password, user.passwordHash); if (!valid) return res.status(401).json({ error: 'Invalid credentials' }); const token = jwt.sign( { userId: user._id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '24h' } ); res.json({ token }); }); // Auth middleware β€” verify token: function authenticate(req, res, next) { const token = req.headers.authorization?..split(' ')[1]; // "Bearer " if (!token) return res.status(401).json({ error: 'No token' }); try { req.user = jwt.verify(token, process.env.JWT_SECRET); next(); } catch { res.status(401).json({ error: 'Invalid token' }); } }
⚠️Security tips: Always hash passwords with bcrypt (never store plain text). Keep JWT secrets in environment variables. Set short expiry times and implement refresh tokens for long sessions. Use HTTPS β€” JWTs in headers are visible if traffic is intercepted.
16
What is CORS and how do you handle it in Node.js?
IntermediateVery Common
+

CORS (Cross-Origin Resource Sharing) is a browser security mechanism that blocks web pages from making requests to a different domain than the one that served them. Node.js APIs need to explicitly allow cross-origin requests.

Node.js
const cors = require('cors'); // Allow all origins (development only!): app.use(cors()); // Allow specific origins (production): app.use(cors({ origin: ['https://myapp.com', 'https://www.myapp.com'], methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'], credentials: true, // allow cookies / auth headers maxAge: 86400 // cache preflight for 24h })); // Dynamic origin (from env / database whitelist): app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin) || !origin) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } } }));
17
How does error handling work in Express.js?
IntermediateVery Common
+
Node.js β€” Express Error Handling
// Custom error class: class AppError extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; } } // Throw from anywhere in a route: app.get('/users/:id', async (req, res, next) => { try { const user = await User.findById(req.params.id); if (!user) throw new AppError('User not found', 404); res.json(user); } catch (err) { next(err); // ← pass to error handler } }); // Async wrapper to avoid try/catch everywhere: const asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next); app.get('/users', asyncHandler(async (req, res) => { const users = await User.find(); // errors auto-forwarded to next() res.json(users); })); // Centralised error handler (LAST middleware, 4 params): app.use((err, req, res, next) => { const status = err.statusCode || 500; const message = err.message || 'Internal Server Error'; if (process.env.NODE_ENV !== 'production') console.error(err.stack); res.status(status).json({ error: message }); });
18
What is rate limiting and why is it important?
Intermediate
+

Rate limiting controls how many requests a client can make in a given time window. It protects APIs from abuse, brute-force attacks, and denial-of-service (DoS) overloads.

Node.js
const rateLimit = require('express-rate-limit'); // General API rate limit: const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // 100 requests per window standardHeaders: true, // return RateLimit-* headers message: { error: 'Too many requests, please try again later' } }); // Stricter limit for auth routes: const authLimiter = rateLimit({ windowMs: 60 * 60 * 1000, // 1 hour max: 5, // 5 login attempts per hour skipSuccessfulRequests: true // only count failed attempts }); app.use('/api', apiLimiter); app.use('/api/login', authLimiter);
19
What is the difference between setImmediate, setTimeout, and process.nextTick?
IntermediateCommon
+
FunctionQueueFires whenUse case
process.nextTicknextTick queue (microtask)Before any I/O, timers, or promises in current iterationDefer until end of current operation
Promise.resolve()Microtask queueAfter nextTick, before any I/OAsync operations
setImmediateCheck phaseAfter I/O events in current loop iterationAfter I/O callbacks
setTimeout(fn, 0)Timers phaseAfter minimum delay (not guaranteed 0ms)Defer to next loop iteration
πŸ’‘Rule of thumb: process.nextTick = "right now but after the current function". setImmediate = "as soon as I/O is done". setTimeout(fn,0) = "at the next available timer slot". Prefer setImmediate over setTimeout(fn,0) inside I/O callbacks for more predictable behavior.
20
How do you validate request data in Express?
Intermediate
+
Node.js β€” express-validator + Zod
// Method 1: express-validator const { body, validationResult } = require('express-validator'); const createUserRules = [ body('email').isEmail().normalizeEmail(), body('password').isLength({ min: 8 }).trim(), body('name').notEmpty().trim().escape(), ]; app.post('/users', ...createUserRules, (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(422).json({ errors: errors.array() }); } // safe to use req.body here }); // Method 2: Zod (TypeScript-friendly) const { z } = require('zod'); const userSchema = z.object({ email: z.string().email(), password: z.string().min(8), name: z.string().min(1), }); app.post('/users', (req, res) => { const result = userSchema.safeParse(req.body); if (!result.success) return res.status(422).json({ errors: result.error }); const { email, password, name } = result.data; // fully typed });
21
What is util.promisify and when would you use it?
Intermediate
+

util.promisify converts a Node.js callback-style function (last argument is (err, result)) into a function that returns a Promise β€” letting you use it with async/await.

Node.js
const { promisify } = require('util'); const fs = require('fs'); // fs.readFile uses old callback style: // fs.readFile(path, options, callback(err, data)) // Promisify it: const readFile = promisify(fs.readFile); async function loadConfig() { const data = await readFile('config.json', 'utf8'); return JSON.parse(data); } // Note: modern Node has fs.promises already: const { readFile: rfp } = require('fs').promises; // Useful for older packages that don't support promises: const dns = require('dns'); const resolve = promisify(dns.resolve); const ips = await resolve('rankweb3.com');

πŸ”₯Advanced QuestionsQ22–Q30

22
What is the Node.js Cluster module and how does it achieve parallelism?
AdvancedCommon
+

Node.js is single-threaded, so by default it only uses one CPU core. The Cluster module lets you spawn multiple Node processes (workers) that share the same server port β€” each running on a separate core.

Node.js
const cluster = require('cluster'); const os = require('os'); const numCPUs = os.cpus().length; if (cluster.isPrimary) { console.log(`Primary ${process.pid} running`); // Fork one worker per CPU core: for (let i = 0; i < numCPUs; i++) { cluster.fork(); } // Restart dead workers: cluster.on('exit', (worker) => { console.log(`Worker ${worker.process.pid} died β€” restarting`); cluster.fork(); }); } else { // Each worker runs the Express app: const app = require('./app'); app.listen(3000); console.log(`Worker ${process.pid} started`); }
πŸ’‘PM2 alternative: In production, most teams use pm2 (pm2 start app.js -i max) instead of managing clusters manually β€” it handles clustering, restarts, logging, and zero-downtime deployments.
23
What are Worker Threads in Node.js?
Advanced
+

Worker Threads allow running JavaScript in separate threads within the same process β€” sharing memory via SharedArrayBuffer. Unlike child processes (Cluster), they're lighter and can share data without serialisation. Ideal for CPU-intensive tasks that would otherwise block the event loop.

Node.js
// main.js: const { Worker, isMainThread, parentPort, workerData } = require('worker_threads'); if (isMainThread) { const worker = new Worker(__filename, { workerData: { numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] } }); worker.on('message', result => console.log('Result:', result)); worker.on('error', console.error); console.log('Main thread not blocked!'); // prints immediately } else { // Runs in the worker thread: const sum = workerData.numbers.reduce((a, b) => a + b, 0); parentPort.postMessage(sum); }
FeatureClusterWorker Threads
MemorySeparate (heavier)Shared memory available
Best forHandling more HTTP requestsCPU-intensive computation
CommunicationIPC (serialised)Messages + SharedArrayBuffer
24
How do you implement caching in a Node.js API?
AdvancedCommon
+
Node.js β€” Redis Caching
const redis = require('ioredis'); const client = new redis(process.env.REDIS_URL); // Cache middleware: function cache(ttlSeconds) { return async (req, res, next) => { const key = `cache:${req.originalUrl}`; const cached = await client.get(key); if (cached) { return res.json(JSON.parse(cached)); // cache hit βœ“ } // Intercept res.json to store in cache: const original = res.json.bind(res); res.json = (data) => { client.setex(key, ttlSeconds, JSON.stringify(data)); return original(data); }; next(); }; } // Use cache on expensive routes: app.get('/api/products', cache(300), async (req, res) => { const products = await Product.find(); // only hits DB on cache miss res.json(products); }); // Invalidate cache on mutation: app.post('/api/products', async (req, res) => { const product = await Product.create(req.body); await client.del('cache:/api/products'); // invalidate stale cache res.status(201).json(product); });
25
What is WebSockets and how do you implement them in Node.js?
AdvancedCommon
+

WebSockets provide a full-duplex, persistent connection between client and server β€” unlike HTTP which is request/response. Once connected, both sides can send messages at any time without re-establishing the connection. Perfect for real-time apps.

Node.js β€” Socket.io
const express = require('express'); const http = require('http'); const { Server } = require('socket.io'); const app = express(); const server = http.createServer(app); const io = new Server(server, { cors: { origin: 'https://myapp.com' } }); // Connection handler: io.on('connection', (socket) => { console.log(`User connected: ${socket.id}`); // Join a room: socket.on('join-room', (roomId) => { socket.join(roomId); }); // Handle chat message: socket.on('chat-message', ({ roomId, message, user }) => { // Broadcast to all in room except sender: socket.to(roomId).emit('chat-message', { message, user }); }); socket.on('disconnect', () => console.log('User disconnected')); }); server.listen(3000);
26
What is the difference between SQL and NoSQL databases? When would you use MongoDB vs PostgreSQL in a Node.js app?
AdvancedVery Common
+
FeaturePostgreSQL (SQL)MongoDB (NoSQL)
SchemaFixed schemaFlexible (schema-less)
Data modelTables + rowsCollections + documents (JSON-like)
Relationshipsβœ… Foreign keys, JOINsManual embedding or references
ACIDβœ… Full ACID transactionsβœ… Since v4 (with sessions)
Best forComplex relationships, financial data, reportingFlexible data, rapid iteration, document storage
Node.js β€” Mongoose vs Prisma
// MongoDB with Mongoose (ODM): const userSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, name: { type: String, required: true }, }); const User = mongoose.model('User', userSchema); // PostgreSQL with Prisma (ORM): // schema.prisma: // model User { // id Int @id @default(autoincrement()) // email String @unique // } const { PrismaClient } = require('@prisma/client'); const prisma = new PrismaClient(); const user = await prisma.user.create({ data: { email, name } });
27
What is microservices architecture and how does Node.js fit into it?
AdvancedCommon
+

Microservices splits an application into small, independent services that each do one thing well, communicate over a network, and can be deployed independently.

  • Node.js strengths for microservices: Fast startup time, low memory footprint, great for I/O-bound services, easy HTTP/gRPC server setup.
  • Service communication: HTTP/REST, gRPC (faster, typed), or message queues (RabbitMQ, Kafka) for async communication.
Node.js β€” Message Queue (Bull)
const Queue = require('bull'); // Producer service β€” add job to queue: const emailQueue = new Queue('email', { redis: process.env.REDIS_URL }); await emailQueue.add({ to: 'user@example.com', subject: 'Welcome to RankWeb3!', template: 'welcome', }, { attempts: 3, // retry 3 times on failure backoff: 5000, // wait 5s between retries delay: 2000, // send after 2s delay }); // Consumer service β€” process jobs: emailQueue.process(async (job) => { await sendEmail(job.data); });
28
What is Node.js memory management and how do you detect memory leaks?
Advanced
+

Node.js uses V8's garbage collector. Memory leaks occur when references to objects are never released, preventing GC from cleaning them up.

Node.js β€” Common Leaks + Detection
// Common leak patterns: // 1. Accidental globals: function leak() { users = []; // ← no const/let = global variable, never GC'd } // 2. Event listeners not removed: emitter.on('data', handler); // ← never cleaned up // Fix: emitter.off('data', handler) when done // 3. Closures holding references: const cache = {}; app.get('/data', (req, res) => { cache[req.ip] = req.body; // grows forever β€” no eviction! }); // Detection tools: // node --inspect app.js β†’ Chrome DevTools heap snapshots // clinic.js β†’ visual memory profiling // heapdump package β†’ programmatic heap snapshots // Monitor in production: setInterval(() => { const mem = process.memoryUsage(); console.log(`Heap: ${Math.round(mem.heapUsed/1024/1024)} MB`); }, 30000);
29
What is graceful shutdown in Node.js and why does it matter?
Advanced
+

Graceful shutdown ensures that when your Node.js process receives a termination signal (e.g., during a deployment or container restart), it finishes in-flight requests before exiting β€” rather than abruptly cutting connections.

Node.js β€” Graceful Shutdown
const server = app.listen(3000); async function shutdown(signal) { console.log(`Received ${signal}, shutting down gracefully...`); // Stop accepting new connections: server.close(async () => { try { // Close DB connections, flush queues, etc.: await mongoose.connection.close(); await redisClient.quit(); console.log('Cleanup complete. Exiting.'); process.exit(0); } catch (err) { console.error(err); process.exit(1); } }); // Force exit after 30s if cleanup hangs: setTimeout(() => process.exit(1), 30000); } process.on('SIGTERM', () => shutdown('SIGTERM')); // Docker/K8s stop process.on('SIGINT', () => shutdown('SIGINT')); // Ctrl+C
30
What are Node.js security best practices?
AdvancedVery Common
+
Node.js β€” Security Checklist
// 1. Use Helmet β€” set security headers: const helmet = require('helmet'); app.use(helmet()); // Sets: CSP, X-Frame-Options, HSTS, X-XSS-Protection, etc. // 2. Input validation β€” never trust user input: const { body } = require('express-validator'); body('email').isEmail().normalizeEmail().trim() // 3. SQL/NoSQL injection prevention: // Use parameterised queries (Prisma, pg) or sanitise with mongoose // ❌ db.query(`SELECT * WHERE id = ${req.params.id}`) // βœ… db.query('SELECT * WHERE id = $1', [req.params.id]) // 4. Rate limiting (see Q18) // 5. Avoid eval() and dynamic code execution // 6. Audit dependencies: // npm audit / snyk test // 7. Run with least privilege (not as root) // 8. HTTPS everywhere β€” never transmit data in plain HTTP // 9. Sanitise error messages in production: if (process.env.NODE_ENV === 'production') { // Return generic errors, not stack traces: res.status(500).json({ error: 'Internal Server Error' }); } // 10. Use security linting: // npm install eslint-plugin-security

Up Next: SQL & Databases

You've covered Node.js. Next in the series is SQL β€” joins, indexes, normalization, transactions, and NoSQL comparisons. Coming very soon.

← HTML & CSS Q&A