MERN Technical Interview Q&A — Accordion

Option B — Collapsible sections. Style: Professional Docs (white + blue). Contains questions, concise answers, demo code and references.

MERN
80+ Q&A • concise answers • demo snippets • references included

1. How does the JavaScript event loop work? Explain with call stack, microtask queue, and macrotask queue.

JS

Answer: The event loop coordinates the call stack and task queues. Synchronous code runs on the call stack. Asynchronous callbacks are scheduled to either the macrotask queue (setTimeout, setInterval, I/O, setImmediate) or microtask queue (Promises .then(), queueMicrotask). After the current stack empties, the engine runs all microtasks before taking the next macrotask.

// Demo: microtask runs before macrotask
console.log('start');
setTimeout(()=>console.log('macrotask'),0);
Promise.resolve().then(()=>console.log('microtask'));
console.log('end');
// Output: start, end, microtask, macrotask

References: MDN Event Loop, MDN Event Loop

2. Difference between var, let, and const (scope, hoisting, TDZ)?

JS

Answer: var is function-scoped, hoisted with undefined. let/const are block-scoped, hoisted but in Temporal Dead Zone until initialization. const cannot be reassigned (but objects are mutable).

// Example
console.log(x); // undefined
var x = 1;
// let y; console.log(y); // ReferenceError if used before initialization
{
  let y = 2;
}

References: MDN let, MDN const

3. What is debouncing and throttling? Implement both.

JS

Answer: Debounce: delay execution until calls stop. Throttle: limit execution to once per interval.

// Debounce
function debounce(fn, ms){
  let t;
  return (...args)=>{ clearTimeout(t); t=setTimeout(()=>fn(...args), ms); };
}

// Throttle
function throttle(fn, ms){
  let last = 0;
  return (...args)=>{
    const now = Date.now();
    if(now - last >= ms){ last = now; fn(...args); }
  };
}

Reference: Debounce vs Throttle

4. What are closures? Give a practical MERN example.

JS

Answer: A closure is a function retaining access to its lexical scope even when executed outside. Useful for factories, memoization, or encapsulating private state.

// Example: request counter middleware in Express using closure
function requestCounter(){
  let count = 0;
  return function(req,res,next){
    count++;
    console.log('requests:', count);
    next();
  }
}
app.use(requestCounter());

Ref: MDN closures

5. Difference between synchronous and asynchronous JS?

JS

Answer: Synchronous code runs sequentially on the call stack. Asynchronous code offloads tasks (I/O, timers, network) and uses callbacks/promises/async-await to resume execution later without blocking the main thread.

6. Explain prototypal inheritance with an example.

JS

Answer: Objects delegate property lookup to their prototype chain. Use Object.create or class sugar.

const person = { greet(){ return 'hi'; } };
const alice = Object.create(person);
console.log(alice.greet()); // 'hi'

// ES6 class
class Person{constructor(name){this.name=name}};
class Student extends Person{constructor(n, id){super(n); this.id=id}}

7. Difference between == and ===?

JS

Answer: == does type coercion then compares; === is strict equality—no coercion. Prefer === to avoid surprises.

8. process.nextTick() vs microtask queue?

Node.js

Answer: In Node.js, process.nextTick() queues a callback to run after the current operation but before other microtasks and I/O. Promises are microtasks that run in the microtask phase. Use process.nextTick carefully as it can starve I/O.

9. What are streams in Node.js? Where used?

Node.js

Answer: Streams are objects for reading/writing continuous data — readable, writable, duplex, transform. Used for files, HTTP, large data processing to avoid buffering whole payloads in memory.

// Pipe a file to response
const fs = require('fs');
app.get('/download', (req,res)=>{
  fs.createReadStream('./big.zip').pipe(res);
});

10. Explain middleware in Express with examples.

Express

Answer: Middleware are functions that have access to req,res,next. They can modify request, end response, or call next(). Examples: logging, body parsing, authentication.

// Simple logger
app.use((req,res,next)=>{ console.log(req.method, req.url); next(); });

11. How does Express handle routing internally?

Express

Answer: Express maintains a stack of route and middleware layers. For each request it iterates layers and matches path/method; matched layer executes. Routers are sub-app stacks.

12. Purpose of app.use()?

Express

Answer: Register middleware (global or path-scoped). Order matters — earlier app.use runs first.

13. Error-handling middleware? How to create one?

Express

Answer: Error middleware has 4 args: (err, req, res, next). Put it after routes.

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

14. Node.js clustering — why needed?

Node.js

Answer: Node is single-threaded per process. Use clustering (cluster module or PM2) to utilize multiple CPU cores by forking worker processes and load-balancing incoming connections.

15. Difference between require and import?

Node / ES Modules

Answer: require() is CommonJS (synchronous). import is ES Modules (static, can be tree-shaken). Node supports both with config & extensions (.mjs / package.json "type":"module").

16. Environment variables — why use .env?

DevOps

Answer: Env vars store config (ports, secrets) separate from code. Use .env for local development (gitignored) and real env vars in production platforms.

17. How to secure APIs in Node.js? (Helmet, rate limiting, CORS)

Security

Answer: Use Helmet to set secure headers, enable CORS carefully, add rate-limiting (express-rate-limit), validate inputs, use HTTPS, sanitize query params, and use JWT with short expiry + refresh tokens.

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

18. What is async/await? How does it behave in the event loop?

JS

Answer: async functions return Promises. await pauses within the async function; control returns to the event loop and the rest executes as microtasks when awaited Promise resolves. Use try/catch for errors.

19. SQL vs NoSQL?

DB

Answer: SQL: relational, structured schema, strong ACID guarantees. NoSQL (MongoDB): document-based, schema-flexible, horizontally scalable — favors fast development and sharding. Choose based on consistency, transaction needs, joins complexity.

20. What is schema-less architecture in MongoDB?

MongoDB

Answer: Documents can have different shapes (fields) inside same collection. Use Mongoose schemas to enforce structure when needed. Schema-less increases agility but requires careful indexing and validation at app level.

21. Purpose of Mongoose schema and model?

Mongoose

Answer: Schema defines the shape, types, defaults, validation. Model is the compiled constructor for creating and querying documents. Models wrap collection operations with helpful APIs.

const UserSchema = new mongoose.Schema({name:String, email:{type:String, required:true}});
const User = mongoose.model('User', UserSchema);

22. What are MongoDB indexes? Types and use cases.

MongoDB

Answer: Indexes speed queries. Types: single field, compound, text, hashed, TTL. Use for query filters, sort fields, unique constraints; avoid over-indexing (writes cost).

23. Aggregation pipeline — important stages?

MongoDB

Answer: Key stages: $match, $group, $project, $sort, $limit, $lookup, $unwind. Pipelines allow powerful transformations server-side.

24. Difference between populate() and $lookup?

MongoDB / Mongoose

Answer: populate() is Mongoose helper that performs extra query(s) to fetch referenced docs. $lookup is aggregation stage that performs server-side join between collections. For complex joins and pipelines, prefer $lookup.

25. How do transactions work in MongoDB?

MongoDB

Answer: Multi-document transactions (on replica sets / sharded clusters) provide ACID semantics using session.startTransaction() and commitTransaction(). Use when multiple docs must change atomically.

26. Sharding vs replication?

MongoDB

Answer: Replication duplicates data across replica set members for high availability. Sharding splits data across shards for horizontal scalability. They can be used together.

27. Mongoose middleware (pre/post hooks)?

Mongoose

Answer: Use schema.pre('save', fn) or schema.post('remove', fn) to run logic before/after operations. Useful for hashing passwords, cascading deletes, audit logs.

28. Designing MongoDB schemas for scalability?

DB Design

Answer: Model access patterns; embed when one-to-few, reference when one-to-many large. Use proper indexes, avoid large arrays, consider bucketing/time-series, and plan shard keys early.

29. Functional vs class components?

React

Answer: Functional components are the modern standard (hooks). Class components use lifecycle methods and state via this.setState. Hooks like useState/useEffect replace lifecycle in a cleaner way.

30. How does React Reconciliation work?

React

Answer: React uses a virtual DOM and performs diffing between render outputs to compute minimal updates. Keys help identify items across renders to preserve identity and minimize DOM operations.

31. What triggers a re-render in React?

React

Answer: Props change, state change, or parent re-render triggers child re-render. Memoization (React.memo, useMemo, useCallback) helps reduce unnecessary renders.

32. How does useMemo help reduce re-renders? Example.

React

Answer: useMemo memoizes a computed value across renders when deps unchanged—avoids expensive recalculations.

const expensive = useMemo(()=> heavyCalc(data), [data]);

33. useCallback vs useMemo?

React

Answer: useCallback memoizes a function reference; useMemo memoizes the result of a computation. useCallback(()=>fn, deps) is shorthand for useMemo(()=>fn, deps).

34. What is useEffect dependency array?

React

Answer: The deps array controls when effect runs (on mount, when deps change, or never). Empty array = run once on mount. Omitting it runs on every render (and can cause loops).

35. What is React Fiber?

React

Answer: React Fiber is the reconciliation algorithm rewrite enabling incremental rendering, priorities, and better scheduling of rendering work (interruptible renders).

36. What is prop drilling and how to avoid it?

React

Answer: Prop drilling is passing props through intermediate components. Avoid via Context API, Redux, Zustand, or lift state to nearest common ancestor or use hooks.

37. Controlled vs uncontrolled components?

React

Answer: Controlled: component state controls form inputs (value from state). Uncontrolled: rely on DOM refs to read values. Controlled favored for validation and predictable state.

38. Lazy loading and code splitting?

React

Answer: Use React.lazy + Suspense or dynamic import() to split bundles and load code on demand. Helps initial load performance.

const Other = React.lazy(()=> import('./Other'));
Loading...
}>

39. What is hydration in React?

React SSR

Answer: Hydration attaches React event listeners to server-rendered HTML so client can take over without re-rendering entire DOM. ReactDOM.hydrate used for SSR outputs.

40. Why do we need keys in lists?

React

Answer: Keys provide stable identity to list items so React can match elements across renders to minimize DOM updates. Use unique stable ids, not indexes for reordered lists.

41. How does Redux work internally? store, reducer, actions?

Redux

Answer: Store holds state and exposes dispatch/getState. Reducers are pure functions computing new state from actions. Middleware intercepts actions to add async behavior (thunk/saga).

42. Redux vs Context API?

State mgmt

Answer: Context provides scoped dependency injection of values; Redux provides a structured global store with devtools, middleware, time-travel, and predictable update patterns. Use Redux for complex shared state and middleware needs.

43. Middleware in Redux? (Thunk / Saga)

Redux

Answer: Middleware wraps dispatch to handle async. Thunk lets actions return functions (dispatch inside). Saga uses generator functions to orchestrate side-effects with better testability for complex flows.

44. How does Zustand differ from Redux? When to use each?

State mgmt

Answer: Zustand is lightweight, no boilerplate, uses hooks-based store. Redux is more structured with devtools and middleware. Use Zustand for simpler local/global state, Redux for large apps requiring strict patterns.

45. Explain JWT internals (header, payload, signature).

Auth

Answer: JWT = base64Url(header).base64Url(payload).signature. Header declares alg/type. Payload holds claims (sub, exp). Signature (HMAC/RSA) verifies integrity. Never store secrets in payload; it's not encrypted by default.

46. What is stateless authentication?

Auth

Answer: Server does not keep session info; token (JWT) contains necessary user data and is validated per request. Easier to scale but revocation handling requires strategies (blacklist, short expiry, refresh tokens).

47. Why store refresh token in HTTP-only cookie?

Security

Answer: HTTP-only cookies are inaccessible to JS, reducing XSS risk. Store refresh tokens there and rotate them. Use SameSite & Secure flags to reduce CSRF risk.

48. Difference between authorization and authentication?

Auth

Answer: Authentication proves identity (login). Authorization decides what an authenticated identity can do (roles, permissions).

49. How to prevent XSS and CSRF?

Security

Answer: XSS: sanitize/escape output, use Content-Security-Policy, avoid innerHTML. CSRF: use SameSite cookies, CSRF tokens for state-changing POST, or store tokens in local storage + double submit pattern (note XSS tradeoffs).

50. Why not store JWT in localStorage?

Security

Answer: localStorage is accessible via JS, vulnerable to XSS-based token theft. Prefer HTTP-only cookies for refresh tokens and short-lived access tokens in memory or secure storage strategies.

51. How does password hashing work? (bcrypt salt rounds)

Security

Answer: Hashing converts password to fixed-length digest. bcrypt adds salt and adjustable rounds to increase compute cost, slowing brute-force attacks. Use a strong work factor (e.g., 10-12) and pepper if needed.

52. REST API constraints?

API

Answer: REST constraints include client-server, statelessness, cacheable responses, uniform interface, layered system, code-on-demand (optional). Following REST aids scalability and simplicity.

53. PUT vs PATCH?

HTTP

Answer: PUT replaces the entire resource (idempotent). PATCH applies partial updates (may or may not be idempotent depending on implementation).

54. What is idempotency in APIs?

API

Answer: An operation is idempotent if repeating it has same effect as once. GET/PUT/DELETE are expected idempotent; POST usually not. Important for retries and safe network operations.

55. Pagination — implement in MongoDB?

DB

Answer: Use skip/limit for simple cases. For large datasets prefer range-based (cursor) pagination using a sort key (e.g., _id or createdAt) for better performance.

// Range pagination
const docs = await collection.find({createdAt: {$lt: lastSeen}}).sort({createdAt:-1}).limit(pageSize);

56. What is rate limiting? How to implement in Express?

Security

Answer: Rate limiting prevents abuse (throttles requests per IP). Use express-rate-limit, or reverse-proxy-level limits (NGINX, Cloudflare) and consider distributed stores (Redis) for multi-instance apps.

57. How does WebSocket differ from HTTP?

Realtime

Answer: HTTP is request/response (stateless). WebSocket establishes a persistent full-duplex TCP connection allowing server push and low latency two-way messaging. Socket.IO builds on WebSocket and adds fallbacks, events, and rooms.

58. Socket.IO rooms and namespaces?

Socket.IO

Answer: Namespaces isolate logic under different endpoints. Rooms are arbitrary channels within a namespace to broadcast to subsets of clients. Use rooms for private chats, groups.

59. Implement private chats using rooms?

Realtime

Answer: Create a room per chat (e.g., user ids combined). Join both participants to room and emit messages to that room. Authenticate socket connection using token middleware.

60. Polling fallback in Socket.IO?

Socket.IO

Answer: Socket.IO can start with long-polling then upgrade to WebSocket if supported. This fallback ensures compatibility with older clients or proxies blocking WebSocket.

61. What is Docker? Why use it?

Docker

Answer: Docker containers package apps with dependencies into portable images. Benefits: consistent environments, easier CI/CD, isolation, faster deployments, and resource efficiency compared to VMs.

62. What is a Dockerfile? Important commands?

Docker

Answer: Dockerfile describes image build. Key commands: FROM, RUN, COPY, ADD, WORKDIR, ENV, EXPOSE, CMD, ENTRYPOINT. Keep layers small and cache-friendly.

# Example Node Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

63. Image vs container?

Docker

Answer: Image is a read-only template; container is a running instance of an image with writable layer. You run containers from images.

64. Best practices for Dockerizing a MERN app?

Docker

Answer: Multi-stage builds, small base images (alpine), environment variables, healthchecks, separate containers per service, use .dockerignore, avoid storing secrets in images, prefer docker-compose or k8s for orchestration.

65. How to run Node.js with PM2 in production?

Deployment

Answer: Use PM2 to manage processes, restarts, clustering, and monitoring. Example: pm2 start server.js -i max --name my-app. Use pm2 ecosystem file for config and startup scripts.

66. What is CI/CD? GitHub Actions example?

DevOps

Answer: CI/CD automates build/test/deploy. GitHub Actions uses workflows (.yml) triggered on push. Example: build test and deploy to Docker Hub or cloud provider on push to main.

67. What is Webpack? loaders and plugins?

Build

Answer: Webpack bundles modules. Loaders transform file types (babel-loader, css-loader). Plugins extend capabilities (HtmlWebpackPlugin). Vite is faster dev server alternative using native ESM.

68. Difference between Vite and CRA?

Frontend

Answer: Vite uses native ESM and a fast dev server with on-demand compilation; CRA uses webpack dev server and full bundling. Vite offers faster cold starts and HMR.

69. Bundling, minification, tree-shaking?

Build

Answer: Bundling concatenates modules into bundles. Minification reduces size by removing whitespace/shortening names. Tree-shaking removes unused exports from final bundles.

70. Design a chat application (WhatsApp-like)?

Design

Answer: Use React client, Socket.IO backend, Node + clustering, MongoDB for message store with appropriate indexes, Redis for session/store and pub/sub, file storage (S3), and consider horizontal scaling with load balancer. Handle presence, delivery receipts, and backpressure.

71. Design scalable authentication system?

Design

Answer: Use stateless access tokens, short expiry, refresh tokens stored in http-only cookies, central auth service (OAuth/JWT), rotate and revoke tokens with a blacklist in Redis when necessary, MFA support, and distributed rate limiting.

72. Design feed system (pagination, infinite scroll)?

Design

Answer: Use cursor-based pagination, prefetch next pages, cache hot feeds (Redis), denormalize feed entries, and use background jobs to generate personalized feeds.

73. Design a notification system?

Design

Answer: Store notifications, use push services (FCM, APNs), websocket channels for realtime, batch delivery via worker queues, and user preferences for channels and throttling.

74. What is caching? Tools (Redis, CDN)?

Perf

Answer: Cache reduces latency by storing computed responses. Use CDN for static assets, Redis for in-memory caching of DB queries, and HTTP caching headers for browser caching.

75. How to optimize MongoDB queries?

DB

Answer: Use appropriate indexes, avoid unbounded skip, project only required fields, analyze with explain(), and denormalize when read-heavy with accepted write complexity.

76. What is load balancing?

Infra

Answer: Distributing incoming traffic across multiple backend instances to improve reliability and capacity. Use round-robin, least-connections, or health-checked algorithms via NGINX, HAProxy, or cloud LB.

77. What is compression? Use compression() in Express?

Perf

Answer: Compression (gzip, brotli) reduces payload size and improves transfer time. Use express compression middleware: const compression = require('compression'); app.use(compression());

78. What is Jest?

Testing

Answer: Jest is a JS testing framework with assertions, mocks, snapshot testing, and built-in runner. Works well for unit and integration tests in Node & React.

79. Integration testing vs unit testing?

Testing

Answer: Unit tests test isolated units (functions/components). Integration tests validate multiple modules working together (DB, API routes). Both are important; E2E tests simulate user flows.

80. How do you test an Express API?

Testing

Answer: Use supertest with Jest/Mocha to spin up app and make requests. Mock DB or use test database, seed data, and teardown between tests.

const request = require('supertest');
const app = require('../app');

describe('GET /users', ()=>{
  it('returns 200', async ()=>{
    await request(app).get('/users').expect(200);
  });
});