Backend Questions for 2+ Dev

 


ROUND 1 – Detailed Answers


1. Explain how the Node.js Event Loop works.

Answer:
Node.js is single-threaded, but it can handle asynchronous and non-blocking operations using the event loop, which is managed internally by libuv. The event loop continuously monitors the call stack and the callback queues.

When the call stack becomes empty, the event loop picks the next callback from the appropriate queue and pushes it onto the call stack for execution. This mechanism enables Node.js to handle I/O operations, timers, and network requests without blocking the main thread.

The event loop runs in six phases, executed in a fixed order:

  1. Timers Phase
    Executes callbacks from setTimeout() and setInterval() whose timers have expired.

  2. Pending Callbacks Phase
    Executes certain system-level callbacks, such as errors from TCP operations.

  3. Idle / Prepare Phase
    Internal phase used by libuv for preparing the poll phase. Developers don’t interact with this phase directly.

  4. Poll Phase
    One of the most important phases.

    • Retrieves new I/O events.

    • Executes callbacks for completed I/O operations.

    • If no pending I/O and no timers, it will wait for incoming events.

  5. Check Phase
    Executes callbacks scheduled by setImmediate().

  6. Close Callbacks Phase
    Executes close events like:

    socket.on("close", () => {});

This cycle repeats continuously, enabling Node.js to remain non-blocking and efficient even with a single thread.


2. What is the difference between require and import in Node.js?

Answer:
require and import are two different module systems in Node.js.

require (CommonJS Module System)

  • Used in older versions of Node.js.

  • Synchronous loading.

  • Uses module.exports and exports.

  • Works out of the box without any configuration.

Example:

const fs = require('fs');

import (ES Module System)

  • Introduced in ES6.

  • Asynchronous and more optimized for modern applications.

  • Uses export keyword to expose functionality.

  • Requires enabling "type": "module" in package.json or using .mjs extension.

  • Supports tree-shaking and works like modern JavaScript in frontend.

Example:

import fs from 'fs';

Summary Table

Featurerequire (CJS)import (ESM)
Module typeCommonJSES Modules
LoadingSynchronousAsynchronous
Exportsmodule.exportsexport
Default supportYesOnly in ESM mode
Tree shakingNoYes

3. How does Express middleware work? Give an example.

Answer:
Middleware in Express is a function that runs between the request and response cycle. It has access to:

  • req (request object)

  • res (response object)

  • next() (function to pass control to the next middleware)

Use cases of middleware:

  • Authentication

  • Logging

  • Validation

  • Parsing request body

  • Error handling

  • Rate limiting

Normal Middleware Example

app.use((req, res, next) => { console.log('Middleware triggered for:', req.url); next(); // passes control to the next middleware });

Error-Handling Middleware Example

Error middleware is special because it has 4 parameters: (err, req, res, next).

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

How middleware works internally:

  1. Express receives request.

  2. Checks middleware stack (ordered list).

  3. Executes each middleware in sequence.

  4. If a middleware does not call next(), the request will hang.

  5. If next(err) is called, Express skips normal middleware and goes to error-handling middleware.


4. How do you handle errors in async/await functions in Node.js and Express?

Answer:
In Node.js, when using async/await, errors can be handled using a try–catch block. However, in Express applications, we normally handle errors using a centralized error-handling middleware so the code stays clean and easy to maintain.

A. Basic try–catch Error Handling

async function getUser() { try { const data = await User.find(); return data; } catch (err) { console.error(err); } }

B. Error Handling in Express Routes

app.get('/users', async (req, res, next) => { try { const users = await User.find(); res.json(users); } catch (err) { next(err); // Pass error to the error-handling middleware } });

C. Centralized Express Error-Handling Middleware

This middleware catches all errors from the entire app.

app.use((err, req, res, next) => { console.error(err.stack); res.status(err.status || 500).json({ success: false, message: err.message || "Internal Server Error", }); });

Why this is important?

  • Avoids repeating try-catch everywhere

  • Provides consistent error response

  • Helps in debugging

  • Makes production logs cleaner


5. How does JWT authentication work? Explain the complete flow.

Answer:
JWT (JSON Web Token) authentication is a stateless authentication mechanism used widely in backend APIs.

Complete Flow:

Step 1: User Login

  • User sends email & password to /login.

  • Backend verifies credentials with database.

Step 2: Server Generates JWT

If credentials are valid:

const token = jwt.sign( { id: user._id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '1h' } );

Token has 3 parts:

  1. Header

  2. Payload (user info)

  3. Signature (important for security)

Step 3: Send Token to Client

Server returns token:

{ "token": "eyJhbGciOi..." }

Step 4: Client Stores Token

Client stores token in:

  • LocalStorage / SecureStorage (mobile apps)

  • HTTP-only cookies (web)

Step 5: Client Sends Token with Every Request

Client adds token in Authorization Header:

Authorization: Bearer <token>

Step 6: Server Verifies Token

Middleware validates token:

const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next();

Step 7: Protected Routes

Only authenticated users can access certain endpoints.


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

Answer:
Both are used to schedule callbacks, but they run in different phases of the event loop.

process.nextTick()

  • Runs before the event loop continues.

  • Higher priority (executes immediately after current operation).

  • Used for microtasks.

  • Can cause event loop delay if overused.

setImmediate()

  • Executes callback in the check phase.

  • Runs after I/O events are processed.

  • Better for heavy tasks that should not block the loop.

Summary Table

Featureprocess.nextTick()setImmediate()
PriorityVery HighNormal
Executes InBefore next event loop tickCheck phase
Use CaseQuick microtasksIO-related tasks
RiskCan block loopNo risk

7. What is the role of libuv in Node.js?

Answer:
libuv is a C library that provides Node.js its asynchronous, non-blocking I/O capabilities. It acts as the backbone of Node.js's concurrency model.

Responsibilities of libuv:

  1. Event Loop Management
    Runs the event loop and manages all phases.

  2. Thread Pool Management
    Used for:

    • File system operations

    • DNS lookups

    • Crypto operations

    • Compression

  3. Cross-platform Abstraction
    Allows Node.js to run consistently on Windows, macOS, and Linux.

  4. Async I/O Handling
    Manages:

    • TCP

    • UDP

    • Pipes

    • File I/O

Why libuv is important?

Without libuv, Node.js would not be asynchronous. It allows Node.js to handle thousands of simultaneous connections efficiently.


8. How does clustering work in Node.js? Why do we use it?

Answer:
By default, Node.js runs on a single thread, even if your machine has 4, 8, or 16 CPU cores.
This limits performance for CPU-intensive applications.

To fix this, Node.js provides the cluster module.

How Clustering Works

  • The master process creates multiple worker processes.

  • Each worker runs a copy of your Node.js application.

  • All workers share the same server port.

  • The OS load-balances incoming requests between workers.

Example:

const cluster = require('cluster'); const os = require('os'); if (cluster.isMaster) { os.cpus().forEach(() => cluster.fork()); } else { // Worker processes require('./server.js'); }

Benefits of Clustering

  • Uses all CPU cores → better performance.

  • Increases throughput under load.

  • Improves reliability (if one worker crashes, master replaces it).

Why Use Clustering?

  • Node.js by default uses only 1 core.

  • Production environments (like PM2) enable clustering for scalability.


ROUND 2 – Detailed Answers (With Examples)


1. Difference Between Synchronous and Asynchronous Programming in Node.js

In Node.js, synchronous programming means that each operation is executed one after another; a task must finish before the next can begin. If a synchronous operation takes time (like reading a large file), it blocks the entire thread and prevents the server from handling other requests. For example:

const data = fs.readFileSync('bigfile.txt'); console.log(data);

This blocks the event loop until the file is fully read.

On the other hand, asynchronous programming allows operations to execute in the background while Node.js continues running other code. Node.js uses callbacks, promises, or async/await to handle asynchronous tasks. For example:

fs.readFile('bigfile.txt', (err, data) => { console.log(data); });

This allows the event loop to continue serving requests while the file is being read.
In backend applications, asynchronous programming is preferred because it enables Node.js to remain non-blocking and handle thousands of concurrent connections efficiently.


2. How the Node.js Thread Pool Works & Tasks That Use It

Node.js itself is single-threaded, but it uses libuv’s thread pool to handle operations that cannot be performed asynchronously at the OS level. The thread pool consists of 4 threads by default, although this can be increased.

Tasks executed in the thread pool include:

  • File system operations (fs.readFile, fs.writeFile)

  • Crypto-intensive tasks (crypto.pbkdf2, scrypt)

  • DNS operations (except DNS.lookup)

  • Compression (zlib.gzip, deflate)

  • Some network operations on Windows

Example:

crypto.pbkdf2("password", "salt", 100000, 64, 'sha512', () => { console.log("Done"); });

This hash computation runs on a background thread, preventing the event loop from being blocked.


3. What Are Streams in Node.js? Types & Use Cases

Streams are objects in Node.js that allow reading or writing data sequentially instead of loading it completely into memory. This makes them ideal for large data processing.

Types of Streams:

  1. Readable Stream – e.g., reading a file

  2. Writable Stream – e.g., writing a log file

  3. Duplex Stream – read + write, e.g., TCP sockets

  4. Transform Stream – modify data while streaming, e.g., compression

Example of using a stream to read a file:

const stream = fs.createReadStream("bigfile.mp4"); stream.pipe(res);

Use cases include file uploads, video streaming, compression, and real-time data processing.


4. What Is CORS in Express and How Does It Work?

CORS (Cross-Origin Resource Sharing) is a mechanism that allows browsers to permit or block requests made from one domain to another. By default, browsers restrict cross-origin requests for security reasons.

When a frontend (e.g., example.com) tries to call an API (api.example.org), the browser sends a preflight request (OPTIONS). The server needs to respond with headers like:

Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, PUT

In Express, enabling CORS is simple:

const cors = require('cors'); app.use(cors());

Internally, Express sets the appropriate HTTP headers so browsers allow the request. Without proper CORS configuration, the browser blocks the call even if the server is running correctly.


5. Difference Between PUT and PATCH (With Examples)

Both PUT and PATCH update data, but they differ in purpose:

PUT

  • Replaces the entire resource

  • Requires full object

Example:

PUT /users/10 { "name": "John", "email": "john@example.com" }

If the user previously had more fields, they may be overwritten.

PATCH

  • Updates only specific fields

  • More efficient for partial updates

Example:

PATCH /users/10 { "email": "john@newmail.com" }

PATCH is preferred in modern REST APIs because it avoids unnecessary data transfer and reduces risk of overwriting data.


6. What Is Rate Limiting and Why It Matters?

Rate limiting restricts how many requests a user or client can make within a certain time frame. It prevents:

  • DDoS attacks

  • API abuse

  • Excessive load on servers

  • Unlimited retry loops

Example using express-rate-limit:

const rateLimit = require("express-rate-limit"); app.use(rateLimit({ windowMs: 1 * 60 * 1000, max: 100 }));

This allows 100 requests per minute per IP.
Rate limiting is essential for API security and maintaining server performance.


7. How MongoDB Indexing Works & When It Can Slow Performance

Indexes in MongoDB work like indexes in a book. Instead of scanning the entire collection, MongoDB uses the index to jump directly to the desired document.

Example:

db.users.createIndex({ email: 1 });

This speeds up queries like:

db.users.find({ email: "abc@gmail.com" });

However, indexes can slow down write operations because MongoDB must update the index every time a document is inserted, updated, or deleted.

Indexes are great for read-heavy applications but may degrade performance in write-heavy systems if overused.


8. What Is the EventEmitter in Node.js?

EventEmitter is a core Node.js class that provides a way to publish and subscribe to events. Many built-in modules use it internally.

Example:

const EventEmitter = require("events"); const emitter = new EventEmitter(); emitter.on("greet", () => console.log("Hello")); emitter.emit("greet");

Modules that use EventEmitter:

  • HTTP server (req, res)

  • Streams

  • Sockets

  • Process module

  • FS watchers

EventEmitter helps create decoupled and event-driven systems.


9. Difference Between Passport.js and JWT Authentication

JWT

  • Stateless (no session storage)

  • Token stored on client

  • Ideal for REST APIs

  • Easy to scale horizontally

Passport.js

  • Middleware-based authentication framework

  • Supports strategies like:

    • Local (email/password)

    • OAuth (Google, Facebook)

    • LDAP

  • Uses sessions by default (stateful)

Passport.js is useful for traditional web apps, while JWT is better for modern APIs and mobile applications.


10. How Load Balancing Works for Node.js Apps

Load balancing distributes incoming requests across multiple Node.js instances to improve performance and reliability.

Common strategies:

  1. Round Robin (most common)

  2. Least Connections

  3. IP Hash

In Node.js deployments, load balancing is often done using:

  • NGINX

  • HAProxy

  • Cloud Load Balancers (AWS, Azure, GCP)

  • PM2 clustering

Example with PM2 clustering:

pm2 start server.js -i max

This starts multiple worker processes to utilize all CPU cores.
Load balancing ensures no single instance becomes overloaded, improving performance and uptime.


🔥 ROUND 3 – Advanced Backend + System Design Interview Questions


1. How would you design a scalable file-upload service (like Google Drive) using Node.js?

A scalable file upload service must handle large files, parallel uploads, failures, and distributed storage.

Architecture

  1. Client uploads in chunks (5–10 MB)

    • Split large files into chunks.

    • Upload each chunk independently → parallel & resumable.

  2. Node.js Upload Server

    • Use multer, busboy, or stream API to handle uploads.

    • Node.js should not buffer entire file in memory → use streams.

  3. Temporary Storage

    • Upload chunks to:

      • AWS S3

      • Google Cloud Storage

      • Local disk (not recommended for production)

  4. Database (MongoDB or PostgreSQL)
    Store:

    • File ID

    • Chunk numbers

    • Upload completion state

    • Metadata (owner, size, timestamps)

  5. Chunk Merging
    When all chunks are uploaded:

    • A background worker (Bull / RabbitMQ) merges chunks into final file.

  6. Security

    • JWT authentication

    • File type validation

    • Antivirus scanning

    • Signed URLs for download

Example Flow

  1. User selects 1 GB file

  2. File splits into 200 chunks (5 MB each)

  3. Client uploads chunks: /upload/:fileId/:chunkNumber

  4. Server stores chunks in S3

  5. When all chunks arrive → worker merges them

  6. Final file becomes downloadable from S3


2. Horizontal Scaling vs Vertical Scaling in Node.js

Vertical Scaling

→ Increasing server capacity

  • More RAM

  • More CPU

  • Faster SSD

Pros: simple
Cons: limited maximum capacity

Horizontal Scaling

→ Adding more Node.js servers

  • Behind a load balancer (NGINX, AWS ELB

  • Use Node.js clusters (multiple processes)

Pros: high availability
Cons: requires stateless apps & shared storage

Example

If your Node.js app is overloaded:

  • Vertical scaling: upgrade from 2 vCPUs → 8 vCPUs

  • Horizontal scaling: run 4 Node.js instances and load balance


3. Explain Database Transactions in MongoDB

MongoDB supports ACID transactions since version 4.x.

How they work

  • Multi-document transactions require replica set or sharded cluster.

  • All operations inside a transaction either commit or abort.

Example

const session = await mongoose.startSession(); session.startTransaction(); try { await User.updateOne({id}, {balance: 500}, {session}); await Order.create([{userId: id, amount: 500}], {session}); await session.commitTransaction(); } catch (err) { await session.abortTransaction(); }

Use cases:

  • Financial payments

  • Multi-step write operations

  • Inventory management


4. What is Redis? How do you use it in Node.js?

Redis is an in-memory data store used for:

  • Caching

  • Rate limiting

  • Pub/Sub

  • Queues

Caching Strategy

Store frequently accessed data:

GET /product/123 → Check Redis → If found: return cached data → If not: query MongoDB → store in Redis → return response

Eviction Policies

  • LRU – Least recently used

  • LFU – Least frequently used

  • TTL – Auto expiry

Node.js Example

const redis = require("redis"); const client = redis.createClient(); client.set("user:101", JSON.stringify(data), "EX", 3600);

5. Design a rate-limited API Gateway (Node.js + Redis)

Goal: Limit each user to X requests per minute.

Architecture

  1. Client → API Gateway (Express)

  2. API Gateway checks Redis

  3. If request count > limit → block

  4. Otherwise → increment counter and allow

Example Algorithm (Token Bucket / Fixed Window)

key = userId:timestamp(minute) if count > 100 → block else increment count & allow

Express Example

app.use(async (req, res, next) => { const key = `rate:${req.user.id}`; let count = await redis.get(key); if (count >= 100) return res.status(429).send("Too many requests"); redis.multi() .incr(key) .expire(key, 60) .exec(); next(); });

6. What is Message Queueing? How do RabbitMQ / Kafka help?

Message queues decouple services by asynchronous communication.

Benefits

  • Handles heavy load

  • Prevents downtime

  • Ensures reliable delivery

  • Enables microservices communication

Use case example

User uploads a video → API triggers “video processing job”

  • API sends message to queue

  • Worker reads message & processes video

RabbitMQ

Good for task queues, job processing

Kafka

Good for event streaming, real-time analytics


7. Designing a Background Job System in Node.js

Use libraries:

  • Bull (Redis-based)

  • Agenda (MongoDB-based)

  • Bree

Why background jobs?

  • Email sending

  • File processing

  • Notification scheduling

  • Data exports

Example using Bull

const Queue = require('bull'); const emailQueue = new Queue('email'); emailQueue.add({ email: "a@b.com" }); emailQueue.process(job => { sendEmail(job.data.email); });

8. Securing an Express API in production

Steps

  1. HTTPS using NGINX or Cloudflare

  2. Helmet.js for secure headers

  3. Rate limiting

  4. Input validation using Joi / Zod

  5. JWT authentication with rotation

  6. CORS configuration

  7. Avoid eval & insecure regex

  8. Environment variables using dotenv

  9. Database sanitization

  10. Disable X-Powered-By header

Example

app.use(helmet()); app.disable("x-powered-by");

9. What is Data Modeling? Design schema for a Social Media Post + Comments

Post Schema

Post { id, userId, content, media[], createdAt, likesCount, }

Comment Schema

Comment { id, postId, userId, text, parentCommentId, // for nested replies createdAt }

Why separate models?

  • Efficient indexing

  • Fetch post separately

  • Scalable for millions of comments

Query Example

Get post + comments:

db.comments.find({ postId: "123" })

10. Debugging Performance Issues in Node.js

Tools

  • clinic.js

  • Chrome DevTools debugger

  • Node Inspector

  • Memory snapshots

  • CPU profiling

  • PM2 monitoring

  • Winston logs

Steps

  1. Detect event loop blocking (clinic flame)

  2. Check long-running sync operations

  3. Analyze heap memory leaks

  4. Check DB slow queries

  5. Add logs for response-time profiling

Example Issue

If an API is slow because of a synchronous loop:

for (let i = 0; i < 1e9; i++) { } // blocks event loop

Solution: offload to worker threads.


11. What is CAP theorem? How does it apply to MongoDB?

CAP = Consistency, Availability, Partition Tolerance

Distributed systems can only guarantee two at a time.

MongoDB (in Replica Sets)

  • Prioritizes Availability + Partition Tolerance

  • Sacrifices Consistency (reads may be stale)

You can tune it using:

  • writeConcern

  • readConcern


12. What is CQRS and Event Sourcing?

CQRS = Command Query Responsibility Segregation

  • Separate models for read and write operations.

  • Reads become faster and scalable.

Event Sourcing

  • Every change is stored as an event (not as final state).

  • System state = replay of events.

Example

Instead of storing:

bankBalance: 5000

We store events:

+1000 deposit -500 withdrawal +4500 deposit

Final balance = sum of events.


13. How do you handle long-running tasks in Node.js without blocking the event loop?

Use:

  • Worker Threads

  • Message Queues

  • Background jobs

  • Offloading CPU-heavy tasks to separate services

Example: CPU-heavy hashing

Replace:

bcrypt.hashSync(password) // blocks

With:

await bcrypt.hash(password, 10)

14. What are WebSockets? How to design real-time chat?

WebSockets provide bi-directional communication.

Architecture

  1. Client connects:
    ws://server.com

  2. Server stores user socket ID

  3. On message → broadcast to recipients

  4. Save messages in DB for persistence

Example

Using Socket.IO:

io.on("connection", socket => { socket.on("send", msg => { io.to(msg.receiverId).emit("receive", msg); }); });

15. How do you break a monolithic Node.js app into microservices?

Steps

  1. Identify boundaries (Auth, Orders, Payments)

  2. Create separate codebases

  3. Each service has:

    • Its own DB

    • Its own deployment

    • Its own scaling

  4. Use API Gateway for routing

  5. Services communicate via:

    • REST

    • gRPC

    • Message Queues (Kafka/RabbitMQ)

Challenges

  • Network latency

  • Data consistency

  • Distributed logging

  • Distributed transactions

  • Versioning APIs


🔥 ROUND 4 – SYSTEM DESIGN + ARCHITECTURE + DEVOPS QUESTIONS

This document contains interview-grade, detailed answers to the Round 4 questions you requested, tailored to a 2–3 year Node.js backend developer. Each question includes: a clear explanation, practical examples, and architecture diagrams (Mermaid) where appropriate.


1. Design a URL Shortener (like Bitly)

Overview A URL shortener maps a long URL to a short code and redirects traffic to the original URL. Key elements: short-code generation, storage, redirect performance, analytics, and scaling.

Components

  • API layer (Node.js + Express)

  • Database (Postgres / MySQL / Redis for hot cache)

  • Unique ID generator (base62 encoding, hash, or snowflake)

  • Cache (Redis)

  • Analytics pipeline (event queue + data store)

Schema (SQL)

CREATE TABLE urls (
id BIGSERIAL PRIMARY KEY,
short_code VARCHAR(16) UNIQUE NOT NULL,
long_url TEXT NOT NULL,
user_id BIGINT NULL,
created_at TIMESTAMP DEFAULT now(),
click_count BIGINT DEFAULT 0
);

Short code generation

  • Option A: Base62 encoding of an auto-increment ID (simple, collision-free). Example: encodeBase62(id).

  • Option B: Hash (MD5/SHA + truncate) — requires collision handling.

  • Option C: NanoID/Snowflake — distributed ID.

Redirect Flow

  1. Client requests GET /:short_code.

  2. App checks Redis cache for short_code → if present, return long URL (HTTP 301). Otherwise, query DB and populate cache.

  3. Increment click counter asynchronously (send event to queue to update analytics).

Scaling & Availability

  • Use Redis as a read-through cache for hot keys.

  • Use multiple app instances behind a load balancer.

  • Use read replicas for analytics queries.

  • Shard DB if write throughput is huge.

Mermaid diagram

flowchart LR
B[User] -->|GET /:code| LB[Load Balancer]
LB --> App[Node.js App]
App --> Redis[Redis Cache]
App --> DB[(Postgres)]
App --> MQ[Message Queue]
MQ --> Analytics[Analytics Worker]

2. Notification Service (email, SMS, push) for millions

Requirements & Constraints

  • High throughput & reliability

  • Multiple channels with differing SLAs (email slower, push faster)

  • Retry & backoff

  • Personalization & templates

  • Opt-out & compliance (CAN-SPAM, GDPR)

Architecture

  • API Gateway (auth & throttling)

  • Ingestion service (Node.js) → validates + enqueues messages

  • Message Queue (Kafka / RabbitMQ / SQS) for durability

  • Worker fleet (autoscaled) for each channel (email, SMS, push)

  • Third-party providers (SES, Twilio, FCM) as downstream

  • Dedup & idempotency logic

  • Monitoring & DLQ (dead-letter queues)

Example flow

  1. App enqueues message to Kafka topic notifications.email.

  2. Consumer picks up message, renders template, calls SES.

  3. On failure, retry with exponential backoff; after N attempts, move to DLQ.

Mermaid diagram

flowchart LR
Client --> API[API Gateway]
API --> Ingest[Ingest Service]
Ingest --> Kafka[Kafka]
Kafka --> Worker_Email[Email Worker]
Kafka --> Worker_SMS[SMS Worker]
Worker_Email --> SES[AWS SES]
Worker_SMS --> Twilio[Twilio]

3. API Gateway vs Reverse Proxy

API Gateway

  • Higher-level features: routing, authentication, rate-limiting, API composition, request/response transformation, versioning, metrics, circuit breaking.

  • Examples: Kong, AWS API Gateway, Tyk, Apigee.

Reverse Proxy

  • Lower-level: simple HTTP proxy for load balancing and TLS offloading.

  • Examples: NGINX, HAProxy.

Key differences

  • API Gateway = application-aware (auth, routing rules, policies). Reverse proxy = transport-level (proxying & LB).

  • Use both: NGINX as edge TLS terminator + API Gateway for app logic.

Mermaid diagram

flowchart LR
Client --> NGINX[NGINX (TLS)]
NGINX --> APIGW[API Gateway]
APIGW --> Services[Microservices]

4. Secrets & Environment Variables in Production

Principles

  • Never check secrets into source control. Use least-privilege access. Rotate secrets regularly.

Solutions

  • Secrets Manager: AWS Secrets Manager, Azure Key Vault, HashiCorp Vault.

  • Container secrets: Kubernetes Secrets (backed by KMS), Docker secrets.

  • CI/CD secrets handling: store encrypted vars in pipeline provider (GitHub Actions secrets, GitLab CI variables).

Example

  • At runtime, app queries Vault using a short-lived token (via IAM role or Kubernetes service account) and retrieves DB credentials.

Mermaid diagram

flowchart LR
App[App] --> Vault[HashiCorp Vault]
Vault --> KMS[KMS]
CI --> Vault

5. CI/CD — Tools & How Pipelines Work

CI/CD Concepts

  • CI (Continuous Integration): run tests & builds on each commit.

  • CD (Continuous Delivery/Deployment): automate deployment to environments.

Common Tools

  • GitHub Actions, GitLab CI, Jenkins, CircleCI, Travis CI, Bitbucket Pipelines.

  • Container registries: Docker Hub, ECR.

  • CD tools: ArgoCD, Flux, Spinnaker.

Pipeline Example (GitHub Actions)

  1. on: push → install deps → run tests → build artifact → publish Docker image to ECR.

  2. deploy job triggered → update Kubernetes manifests → apply to cluster (kubectl / ArgoCD).

Mermaid diagram

flowchart LR
Dev --> Repo[GitHub]
Repo --> CI[GitHub Actions]
CI --> Registry[Docker Registry]
CI --> K8s[Deploy to Kubernetes]

6. Docker: Images, Containers, Volumes, Networks

Docker basics

  • Image: immutable filesystem snapshot (built from Dockerfile).

  • Container: runtime instance of an image.

  • Volumes: persist data outside container lifecycle.

  • Networks: connect containers.

Why Docker matters

  • Reproducible environments, faster onboarding, easier CI builds, consistent runtimes across environments.

Example

FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . ./
CMD ["node", "server.js"]

7. Deploy Node.js on AWS (EC2 / ECS / Elastic Beanstalk)

EC2 (manual)

  • Provision EC2 instance(s)

  • Install Node, PM2

  • Deploy artifacts (SCP/CI)

  • Use NGINX as reverse proxy

  • Use Auto Scaling Groups and Load Balancer

ECS (containerized)

  • Build Docker image → push to ECR

  • Define Task Definition & Service

  • Use ALB for load balancing

  • Auto scale based on CPU/memory

Elastic Beanstalk (PaaS)

  • Deploy app bundle → Beanstalk handles infra

  • Easy but less control

Mermaid diagram (ECS)

flowchart LR
Dev --> CI[CI Pipeline]
CI --> ECR[Docker Registry]
ECR --> ECS[ECS Service]
ECS --> ALB[ALB]
ALB --> Users[Users]

8. Load Balancing Strategies

Round Robin

  • Distributes requests sequentially across all servers.

Least Connections

  • Sends requests to server with fewest active connections.

IP Hash

  • Uses client IP to consistently route to the same backend.

When to use

  • Round robin: general purpose

  • Least connections: uneven request durations

  • IP hash: sticky sessions without a session store


9. Monitoring Node.js in Production

Key signals

  • Logs (structured JSON) — Winston, Bunyan

  • Metrics — Prometheus + Grafana (latency, request rate, error rate)

  • Traces — Jaeger / OpenTelemetry

  • APM — NewRelic, DataDog

  • Health checks & alerting (uptime)

Practical setup

  • Expose /healthz and /metrics

  • Export metrics via prom-client

  • Centralized log storage (ELK / EFK / CloudWatch)


10. CDN and Performance

CDN purpose

  • Serve static assets from edge locations close to users.

  • Reduce latency and origin load.

Use cases

  • Images, JS/CSS, downloads, video streaming (with signed URLs).

Providers

  • CloudFront, Fastly, Cloudflare, Akamai.


11. Database Sharding

Sharding

  • Horizontal partitioning of data across multiple nodes.

When to shard

  • Data size exceeds single-node capacity

  • Write throughput limits

MongoDB

  • Use shard key with even distribution

  • Consider chunk migrations and balancing

Postgres

  • Use Citus or custom hash-based sharding


12. Analytics System for Millions of Events

Requirements

  • High ingest rate, durable, low cost, near real-time processing

Pipeline

  • Client → Event collector (stateless Node.js) → Kafka (or Kinesis)

  • Stream processors (Flink / Spark Streaming / Kafka Streams)

  • Storage: hot store (Elasticsearch / ClickHouse) + cold store (S3 / Parquet)

  • Dashboard & aggregation

Mermaid diagram

flowchart LR
Client --> Collector[Event Collector]
Collector --> Kafka[Kafka]
Kafka --> StreamProc[Stream Processors]
StreamProc --> ClickHouse[ClickHouse]
StreamProc --> S3[S3]

13. API Rate Limiter vs Throttling

Rate limiting

  • Caps number of requests allowed per client in a time window (e.g., 100/min).

Throttling

  • Slows down the request processing rate (e.g., delay or queue) rather than rejecting.

Use both

  • Use rate-limiter to prevent abuse; throttling to smooth bursts.


14. Multi-tenant SaaS: Shared DB vs Separate DB

Shared DB (schema per tenant or single schema)

  • Pros: cheaper, easier to manage

  • Cons: noisy neighbor, harder isolation

Separate DB per tenant

  • Pros: strong isolation, easy backup/restore per tenant

  • Cons: operational overhead, scaling many DBs

Hybrid

  • Small tenants in shared DB, large tenants on dedicated DBs


15. Zero-downtime Deployment

Strategies

  • Blue/Green deploys (switch traffic after verification)

  • Rolling updates with health checks

  • Use of readiness and liveness probes in Kubernetes

Practical steps (K8s)

  • Deploy new ReplicaSet with new image

  • Wait for readiness; then gradually scale down old RS

  • Use readinessProbe to avoid sending traffic to not-ready pods


16. Secure API Keys & Secrets in CI/CD

Approach

  • Store secrets in pipeline secret store (encrypted). Use Vault or cloud KMS.

  • Never echo secrets in logs. Use masked variables.

  • Use ephemeral credentials (short-lived tokens via IAM roles).


17. Blue-Green vs Rolling Deployment

Blue-Green

  • Two environments (blue = current, green = new). Switch router/traffic after validation.

  • Pros: instant rollback.

Rolling

  • Replace instances gradually. Fewer resources but slower rollback.


18. Idempotency in APIs

Definition

  • An idempotent operation can be applied multiple times without changing the result beyond the initial application.

Idempotent HTTP methods

  • GET, PUT, DELETE are idempotent. POST is not by default.

Idempotency keys

  • For POSTs that create resources, use idempotency-key header to ensure single side-effe



🔥 ROUND 5 – ADVANCED BACKEND + ARCHITECTURE QUESTIONS

1. Explain different caching strategies (Write-through, Write-back, Write-around). Which one is best for high-read systems?


**2. How do you design a real-time collaborative editor (like Google Docs)?

Explain OT / CRDTs and conflict resolution.**


3. What is eventual consistency? Where is it used in real-world systems like WhatsApp or Instagram?


**4. How do you design pagination for a large dataset (1M+ rows)?

Offset-based vs cursor-based pagination?**


5. What is a Dead Letter Queue (DLQ) and how do Kafka / RabbitMQ use it?


6. Explain Saga Pattern in microservices. Why is it used instead of distributed transactions?


7. How would you design an email scheduling system (send emails at specific times)?


8. What is a distributed lock? When would you use Redis RedLock?


9. Explain Webhooks. How do you design them so that they are reliable and retry on failure?


10. How would you design a search system like Amazon product search (Elasticsearch + Indexing)?


11. Explain the difference between Monolithic, Microservices, and Modular Monolith architectures.


12. How do you implement soft deletes in databases? Pros/cons?


13. What is a Bloom Filter? How can it improve performance in Redis or search engines?


14. Explain API versioning and different versioning strategies.


15. What is throttling vs debouncing? How can these be applied at API level?


16. How would you store and serve large media files (videos/images) efficiently in a Node.js app?


17. What is Circuit Breaker Pattern? How does it prevent cascading failures?


**18. How do you design a leaderboard system (like gaming apps)?

Explain sorted sets in Redis.**


19. What are read replicas? How do they improve scalability in databases?


20. Explain connection pooling in databases. Why is it always used?


ROUND 6 – SECURITY + PERFORMANCE QUESTIONS

21. Explain OAuth2 in detail (authorization code flow).


22. What is HMAC? How is HMAC used to secure API communication?


23. How do you prevent race conditions in Node.js applications?


24. What is a memory leak in Node.js? How do you detect and fix it?


25. How does HTTPS work internally? Explain certificates, TLS handshake, symmetric/asymmetric encryption.


26. How do you implement file encryption + decryption in Node.js (AES)?


27. What is CORS? How do you configure it securely?


28. Explain SQL indexing. What types of indexes exist?


29. How do you prevent brute-force login attacks?


30. What is heap vs stack memory in JavaScript V8?


⚙️ ROUND 7 – ADVANCED NODE.JS INTERNALS

31. Explain Node.js worker threads vs child processes. When to use which?


32. What is clustering in Node.js? How does PM2 handle it?


33. How does Node.js handle backpressure in Streams?


34. Explain Zero-Downtime Restart with Node.js Cluster.


35. How does Node.js garbage collection work? (V8 GC algorithm)



Post a Comment

Previous Post Next Post