Skip to content

MERN Stack Interview Questions in Gurgaon

36 practice questions with answers for MERN Stack interviews in Gurgaon.

MERN Stack jobs in Gurgaon

Gurgaon (Gurugram) is home to many multinational, consulting, fintech and consumer-internet offices. Interviews often expect strong business understanding along with technical skills, especially for analytics and product-facing roles.

Below are 36 questions that match the mix of service, product and domain employers hiring mern stack developers in Gurgaon.

Solved for GurgaonStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

Attackers are trying thousands of passwords on your login endpoint. How do you defend it?

Save to ▾
Show answer
Apply strict rate limits on login per IP and per account using a shared Redis store, add progressive delays or temporary account lockout after several failures, and show a CAPTCHA after repeated attempts. Return a generic error message so attackers cannot tell whether an email exists. Log and alert on spikes, check for breached passwords at signup, and offer two-factor authentication for sensitive accounts.
02

Write a role-based authorization middleware for Express.

Save to ▾
Show answer
A small factory function keeps routes readable. export const authorize = (...roles) => (req, res, next) => { if (!req.user) return res.status(401).json({ message: 'Login required' }); if (!roles.includes(req.user.role)) { return res.status(403).json({ message: 'Forbidden' }); } next(); }; router.delete('/products/:id', requireAuth, authorize('admin'), deleteProduct); router.patch('/articles/:id', requireAuth, authorize('admin', 'editor'), updateArticle); It must run after the authentication middleware that sets req.user.
03

How does Supertest help test Express APIs?

Save to ▾
Show answer
Supertest sends HTTP requests directly to your Express app object without starting a real server on a port, and lets you assert on status codes, headers and bodies. This is why you export the app separately from the server.listen call. Combine it with an in-memory MongoDB using mongodb-memory-server or a dedicated test database, seeding data before each test and clearing it afterwards.
04

What is the difference between props and state in React?

Save to ▾
Show answer
Props are inputs passed from a parent to a child component; they are read-only inside the child. State is data owned and managed by a component itself, created with useState or useReducer, and changing it triggers a re-render. A common pattern is that a parent keeps state and passes both the value and a setter function down as props to children.
05

Explain destructuring, the spread operator and rest parameters.

Save to ▾
Show answer
Destructuring unpacks values from arrays or objects into variables, for example const { name, email } = user, with optional defaults and renaming. Spread (...) expands an iterable or object, used to copy arrays, merge objects or pass arguments. Rest uses the same syntax to collect remaining items, as in function sum(...nums) or const { password, ...safeUser } = user. In React, spread is used constantly to create new state objects immutably.
06

Your script crashes with out of memory while reading a 5 GB log file. How would you rewrite it?

Save to ▾
Show answer
fs.readFile loads the whole file into memory, which exceeds the heap. Use a stream instead: fs.createReadStream with readline lets you process one line at a time with for await, keeping memory flat. If you need to transform and write output, connect read, transform and write streams with pipeline so backpressure and errors are handled. Increasing --max-old-space-size only hides the real problem.
07

Tell me about a time you had to learn a new JavaScript concept quickly to finish a task.

Save to ▾
Show answer
Situation: in my final-year project our dashboard froze while loading data from three APIs. Task: I had to fix it before the demo in two days. Action: I studied Promises and async/await properly, rewrote the nested callbacks, and used Promise.all to load the APIs in parallel with proper error handling. Result: load time dropped from 6 seconds to under 2, and I documented the pattern for my team.
08

How would you structure the folders of a production Express API?

Save to ▾
Show answer
A layered structure keeps responsibilities clear: src/routes for route definitions, src/controllers for request and response handling, src/services for business logic, src/models for Mongoose schemas, src/middlewares for auth, validation and errors, src/config for environment and database setup, src/utils for helpers, and tests alongside or in a tests folder. Keep app.js, which builds the app, separate from server.js, which listens, so tests can import the app.
09

Describe a production issue you handled in a Node.js service.

Save to ▾
Show answer
Situation: our order API started timing out every evening at peak. Task: as the on-call developer I had to restore it. Action: I checked logs and metrics, found event-loop lag spikes, and traced them to a synchronous CSV export running inside a request. I moved the export to a background job and added event-loop lag alerts. Result: p95 latency dropped from 4 seconds to 300 ms and timeouts stopped.
10

Write a React Testing Library test for a counter button.

Save to ▾
Show answer
Query by role and simulate real user events. import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import Counter from './Counter'; test('increments the count when + is clicked', async () => { const user = userEvent.setup(); render(<Counter />); expect(screen.getByText('Count: 0')).toBeInTheDocument(); await user.click(screen.getByRole('button', { name: '+' })); expect(screen.getByText('Count: 1')).toBeInTheDocument(); }); toBeInTheDocument comes from @testing-library/jest-dom.
11

Props are being passed through five levels of components that do not use them. How would you refactor?

Save to ▾
Show answer
This is prop drilling. First try component composition: pass ready-made elements as children or props so intermediate components do not need the data. If many distant components need it, create a Context with a custom hook like useAuth. For complex or frequently updated shared state, use a store such as Zustand or Redux Toolkit with selectors so only interested components re-render.
12

Show how to create and use a custom EventEmitter.

Save to ▾
Show answer
Extend EventEmitter to emit domain events. import { EventEmitter } from 'node:events'; class OrderService extends EventEmitter { place(order) { // save order... this.emit('order:placed', order); } } const orders = new OrderService(); orders.on('order:placed', (o) => sendEmail(o.userEmail)); orders.once('order:placed', () => console.log('first order')); orders.place({ id: 1, userEmail: 'a@b.com' }); Listeners run synchronously in registration order.
13

Why do applications use both access tokens and refresh tokens?

Save to ▾
Show answer
The access token is short-lived, for example 15 minutes, and is sent with every API request, so if stolen it is useful only briefly. The refresh token is long-lived, stored more securely in an httpOnly cookie, and is used only at a refresh endpoint to get new access tokens. Refresh tokens should be stored server-side or hashed so they can be revoked, and rotated on every use to detect theft.
14

Fast typing in a search box sometimes shows results for an older query. What causes this and how do you fix it?

Save to ▾
Show answer
It is a race condition: responses arrive out of order, so a slow earlier request overwrites results of a newer one. In the effect, use an AbortController and abort the previous request in the cleanup, or keep an ignore flag set to true during cleanup and skip setState when it is set. Debouncing reduces requests, and TanStack Query handles this automatically by keying results to the query.
15

An error in one dashboard widget crashes the entire React page. How do you contain it?

Save to ▾
Show answer
Wrap risky sections in error boundaries. An error boundary catches rendering errors in its subtree and shows fallback UI instead of unmounting the whole app. React still requires a class with getDerivedStateFromError and componentDidCatch, or you can use the react-error-boundary package. Place boundaries around each widget and the route level, log errors to monitoring, and offer a retry. They do not catch errors in event handlers or async code.
16

What is the difference between process.nextTick, setImmediate and setTimeout(fn, 0)?

Save to ▾
Show answer
process.nextTick queues a callback to run right after the current operation, before Promise microtasks and before the event loop continues. setImmediate runs in the check phase after poll. setTimeout with 0 runs in the timers phase once at least about 1 ms has passed. Overusing nextTick recursively can starve I/O, so setImmediate is the safer way to defer heavy work.
17

What are the core principles of a RESTful API, and which HTTP methods are idempotent?

Save to ▾
Show answer
REST models data as resources identified by URLs, uses standard HTTP methods, is stateless, and returns representations like JSON with proper status codes. Use nouns, for example GET /orders and POST /orders. GET, PUT, DELETE, HEAD and OPTIONS are idempotent: repeating them gives the same server state. POST is not idempotent, and PATCH usually is not, which matters when clients retry requests.
18

What is the Context API and when should you avoid it?

Save to ▾
Show answer
Context passes data through the component tree without prop drilling. You create it with createContext, provide a value with a Provider and read it with useContext, or the newer use API. It suits low-frequency global data like theme, language and logged-in user. Avoid it for frequently changing large state, because every consumer re-renders when the value changes; split contexts or use Zustand or Redux Toolkit instead.
19

Write a debounce function in JavaScript.

Save to ▾
Show answer
Debounce delays a call until a quiet period has passed. Each new call clears the previous timer. function debounce(fn, delay = 300) { let timer; return function (...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } const onSearch = debounce((q) => fetchResults(q), 400); It relies on a closure over timer and keeps this and arguments intact.
20

Write a production Dockerfile for a Node.js Express API.

Save to ▾
Show answer
Keep the image small and run as a non-root user. FROM node:22-alpine WORKDIR /app ENV NODE_ENV=production COPY package*.json ./ RUN npm ci --omit=dev COPY src ./src USER node EXPOSE 5000 CMD ["node", "src/server.js"] Copying package files first lets Docker cache the dependency layer, so code changes rebuild quickly. Add a .dockerignore with node_modules and .env.
21

How do you debug a JavaScript bug that a user reports but you cannot reproduce locally?

Save to ▾
Show answer
Situation: a user reported a checkout button doing nothing, but it worked for me. Task: find the cause quickly. Action: I asked for browser, device and steps, checked our error-tracking logs, and found a TypeError only on an older Safari version due to an unsupported method. I reproduced it on a cloud device, added a polyfill and a test. Result: the fix shipped the same day and I added browser targets to our build.
22

What is the difference between authentication and authorization?

Save to ▾
Show answer
Authentication verifies who the user is, for example by checking email and password, an OTP or a Google login, and results in a session or token. Authorization decides what that authenticated user may do, such as whether a normal user can delete products or only an admin can. Failed authentication should return 401 Unauthorized, while an authenticated user lacking permission should get 403 Forbidden.
23

Your Express API slows down badly during peak traffic. How do you find and fix the bottleneck?

Save to ▾
Show answer
Measure first: add request timing logs or APM tracing to find slow endpoints, then check whether time goes to the database, external calls or CPU. Use explain() for slow queries and add indexes, cache hot read endpoints in Redis, enable compression, paginate large responses and remove synchronous code from handlers. Then scale horizontally with multiple instances behind a load balancer and load test with k6 or autocannon.
24

Explain the phases of the Node.js event loop.

Save to ▾
Show answer
Each loop iteration goes through phases: timers runs expired setTimeout and setInterval callbacks; pending callbacks runs some deferred system callbacks; poll waits for and runs I/O callbacks; check runs setImmediate callbacks; close callbacks handles events like socket close. Between every callback, Node drains process.nextTick callbacks and then Promise microtasks. Knowing this explains why setImmediate inside an I/O callback always runs before a setTimeout of 0.
25

Fetch a list of users from an API inside useEffect with proper cleanup.

Save to ▾
Show answer
AbortController cancels the request if the component unmounts. function Users() { const [users, setUsers] = useState([]); const [error, setError] = useState(null); useEffect(() => { const controller = new AbortController(); fetch('/api/users', { signal: controller.signal }) .then((r) => r.json()) .then(setUsers) .catch((e) => { if (e.name !== 'AbortError') setError(e); }); return () => controller.abort(); }, []); if (error) return <p>Failed to load</p>; return <ul>{users.map((u) => <li key={u._id}>{u.name}</li>)}</ul>; }
26

What is the difference between req.params, req.query and req.body?

Save to ▾
Show answer
req.params holds named route segments, so for /users/:id a request to /users/42 gives req.params.id equal to '42'. req.query holds the query string, so ?page=2&sort=name gives { page: '2', sort: 'name' }. req.body holds the parsed request payload, available only after a parser like express.json(). Params and query values are strings, so convert and validate them before use.
27

A developer accidentally pushed the .env file with the MongoDB password and JWT secret to a public repository. What do you do?

Save to ▾
Show answer
Treat the secrets as compromised immediately. Rotate the MongoDB user password, the JWT secret and any API keys; rotating the JWT secret logs everyone out, which is acceptable. Check database and cloud logs for suspicious access. Remove the file, add .env to .gitignore, and purge it from history with a tool like git filter-repo, though rotation matters more. Enable secret scanning and pre-commit hooks to prevent repeats.
28

Design a secure forgot-password flow for a MERN application.

Save to ▾
Show answer
The user submits an email; always respond with the same message whether or not it exists. Generate a random token with crypto.randomBytes, store only its hash with an expiry of around 15 minutes, and email a link with the raw token. On submission, hash the token, find a matching unexpired record, set the new hashed password, delete the token and invalidate existing sessions. Rate limit the endpoint.
29

What are streams in Node.js and what types exist?

Save to ▾
Show answer
Streams process data in chunks instead of loading it all into memory. The four types are Readable (file read, HTTP request), Writable (file write, HTTP response), Duplex (TCP socket) and Transform (gzip, encryption), which modifies data as it passes. Streams handle backpressure, pausing the source when the destination is slow. pipeline() from node:stream/promises connects them safely and handles errors and cleanup.
30

Write a central error-handling middleware with a custom AppError class.

Save to ▾
Show answer
One handler keeps responses consistent. class AppError extends Error { constructor(message, statusCode = 500) { super(message); this.statusCode = statusCode; this.isOperational = true; } } function errorHandler(err, req, res, next) { if (err.code === 11000) err = new AppError('Duplicate value', 409); const status = err.statusCode || 500; res.status(status).json({ message: err.isOperational ? err.message : 'Something went wrong' }); } app.use(errorHandler); // register last
31

What is NoSQL injection and how do you prevent it in a MongoDB app?

Save to ▾
Show answer
NoSQL injection happens when user input is placed directly into a query and contains operators. For example, a login body of { email: 'a@b.com', password: { $ne: null } } could match any password if passed straight to findOne. Prevent it by validating types with zod or Joi, casting inputs to strings, stripping keys starting with $ or containing dots, enabling Mongoose strictQuery, and never building $where queries from user input.
32

Group an array of order objects by their status using reduce.

Save to ▾
Show answer
reduce builds an object whose keys are statuses and values are arrays. const grouped = orders.reduce((acc, order) => { (acc[order.status] ||= []).push(order); return acc; }, {}); // { paid: [...], pending: [...] } Newer runtimes also offer Object.groupBy(orders, (o) => o.status), which returns the same shape with a null prototype.
33

What does lean() do in Mongoose and when should you use it?

Save to ▾
Show answer
By default Mongoose queries return full documents with change tracking, getters, virtuals and methods like save. Calling .lean() returns plain JavaScript objects, which uses much less memory and is noticeably faster. Use it for read-only endpoints such as lists and API responses. Skip it when you need to modify and save the document, or depend on virtuals and getters unless you add a lean plugin.
34

What is the difference between app.use, app.get and express.Router?

Save to ▾
Show answer
app.use mounts middleware for all HTTP methods on a path prefix, so app.use('/api', fn) runs for /api/anything. app.get registers a handler only for GET requests matching that exact path pattern. express.Router creates a mini application with its own routes and middleware, which you mount with app.use('/api/users', userRouter). Routers keep large projects modular, with one file per resource.
35

What is a closure and where is it useful?

Save to ▾
Show answer
A closure is a function that remembers the variables of the scope where it was created, even after that outer function has returned. For example, a makeCounter function can return an inner function that increments a private count variable. Closures power data privacy, function factories, memoization, debounce and throttle helpers, and React hooks, where event handlers capture props and state from the render that created them.
36

Describe a mistake you made with data and how you handled it.

Save to ▾
Show answer
Situation: I ran an update script against the staging database with a wrong filter and modified thousands of records. Task: restore data before QA testing next morning. Action: I informed my lead immediately, restored from the nightly backup, re-applied the day's valid changes, and then added a dry-run mode and a count confirmation step to our scripts. Result: QA was not blocked, and no similar incident happened again.

Companies with offices in Gurgaon (6)

Frequently asked questions

Which companies hire MERN Stack professionals in Gurgaon?

Companies with large offices in Gurgaon include Accenture, Nagarro, Publicis Sapient, GlobalLogic, EPAM Systems, Zomato. Use their company pages below to practise employer-specific sets.

Are MERN Stack interviews in Gurgaon different from other cities?

The questions depend more on the company than the city. Gurgaon's mix of employers decides the style: Interviews often expect strong business understanding along with technical skills, especially for analytics and product-facing roles

How do I find MERN Stack jobs in Gurgaon?

Shortlist companies with Gurgaon offices, keep your CV focused on MERN Stack projects, apply on company career pages and job portals with the Gurgaon filter, and practise the questions on this page before each interview.