MERN Stack Interview Questions for 1 Year Experience
40 questions with answers for candidates with 1 year of experience — 17 easy, 21 medium, 2 hard.
What interviewers expect: 1 year experience
With one year of experience, interviewers expect you to have shipped real features. They ask about your daily work, how you fetch and manage data in React, how you structure Express projects, validation, error handling and JWT authentication. Expect practical tasks like writing middleware, a custom hook or an aggregation, plus questions on Git workflow, code reviews and debugging bugs reported by QA.
This set is weighted towards React Fundamentals (8), Testing, Deployment and DevOps (8), MongoDB and Mongoose (6), Express.js and REST APIs (5).
Feature delivery Custom hooks API structure and validation Debugging
Solved at this levelStart 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
A developer accidentally pushed the .env file with the MongoDB password and JWT secret to a public repository. What do you do?
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.
02
A component calls setState inside useEffect and the app goes into an infinite render loop. Why?
The effect updates state, which re-renders, which runs the effect again. This happens when the dependency array is missing, or when a dependency is a new object or array created every render, or when the effect sets the same state it depends on. Add correct dependencies, move object creation inside the effect or memoize it, and ask whether the value can be calculated during render instead.
03
What is NoSQL injection and how do you prevent it in a MongoDB app?
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.
04
Write Express middleware that logs method, URL, status code and response time.
Hook into the response finish event to know the final status.
function requestLogger(req, res, next) {
const start = process.hrtime.bigint();
res.on('finish', () => {
const ms = Number(process.hrtime.bigint() - start) / 1e6;
console.log(`${req.method} ${req.originalUrl} ${res.statusCode} ${ms.toFixed(1)}ms`);
});
next();
}
app.use(requestLogger);
In production, use a structured logger like pino instead of console.log.
05
What is the difference between req.params, req.query and req.body?
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.
06
What is the difference between unit, integration and end-to-end tests in a MERN app?
Unit tests check a single function or component in isolation, such as a price calculator or a button, and are fast. Integration tests check pieces working together, such as an Express route with a real test database using Supertest. End-to-end tests drive the full app in a real browser with Playwright or Cypress, for example signup to checkout. Keep many unit tests, fewer integration tests and a small set of critical E2E flows.
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.
08
What is mocking and when should you mock in tests?
Mocking replaces a real dependency with a controlled fake so tests are fast, isolated and deterministic. Mock things you do not own or that are slow or unpredictable: payment gateways, email services, third-party APIs, time and random values. In React tests, Mock Service Worker intercepts network requests. Avoid mocking everything, especially your own database layer in integration tests, or tests will pass while real code fails.
09
Compare offset-based and cursor-based pagination for an API.
Offset pagination uses page and limit, translating to skip and limit in MongoDB. It is simple and allows jumping to page 10, but gets slower on large collections and can skip or repeat items when data changes. Cursor pagination returns items after a stable sorted value, such as the last _id or createdAt, using an indexed range query. It stays fast and consistent, ideal for infinite scroll feeds.
10
Describe a production issue you handled in a Node.js service.
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.
11
What is the difference between == and === in JavaScript?
== compares values after type coercion, so 0 == '0' and null == undefined are both true. === compares value and type without coercion, so 0 === '0' is false. Coercion rules are hard to remember and cause subtle bugs, so teams use === everywhere, often enforced by an ESLint rule. A common accepted exception is value == null, which checks for both null and undefined in one step.
12
How do environment variables work in a Vite React app compared to a Node.js backend?
In Node, process.env is read at runtime on the server, so secrets are safe there. In a Vite app, only variables prefixed with VITE_ are exposed, through import.meta.env, and they are embedded into the JavaScript bundle at build time. Anything in the frontend bundle is public, so never put database passwords or secret keys there. Changing a frontend variable requires a rebuild.
13
Explain destructuring, the spread operator and rest parameters.
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.
When two or more components need the same data, you move that state to their closest common parent and pass it down as props, along with functions to update it. For example, a filter bar and a product list both depend on the selected category, so the page component holds the category state. This keeps one source of truth and avoids components getting out of sync.
15
Write a Supertest integration test for a POST /api/users endpoint.
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.
17
Build a simple todo list in React with add and delete.
JSX is a syntax extension that lets you write HTML-like markup inside JavaScript. A compiler such as Babel, esbuild or SWC, used by Vite, turns each element into a function call that creates a React element object. JSX supports JavaScript expressions inside curly braces, uses className instead of class and htmlFor instead of for, and requires one parent element or a fragment.
21
What is the difference between CommonJS and ES modules in Node.js?
CommonJS uses require and module.exports, loads synchronously and is the historic Node default. ES modules use import and export, are statically analysable, support top-level await and enable tree shaking. Node treats .mjs files, or .js files when package.json has type: module, as ESM. Modern Node versions can even require synchronous ES modules, but mixing systems still needs care, so new MERN projects usually pick ESM throughout.
22
What is the difference between app.use, app.get and express.Router?
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.
23
What is the difference between process.nextTick, setImmediate and setTimeout(fn, 0)?
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.
24
Create a basic HTTP server in Node.js without Express that returns JSON.
The built-in node:http module is enough for simple servers.
import http from 'node:http';
const server = http.createServer((req, res) => {
if (req.method === 'GET' && req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
return res.end(JSON.stringify({ status: 'ok' }));
}
res.writeHead(404);
res.end();
});
server.listen(3000, () => console.log('Listening on 3000'));
Express adds routing, middleware and body parsing on top of this.
25
How do you protect certain routes in React so that only logged-in users can access them?
Create a ProtectedRoute or layout component that reads auth state from context. If the user is not authenticated, return <Navigate to='/login' replace state={{ from: location }} />, otherwise render the Outlet or children. Show a loader while the session check is pending to avoid flicker. Remember that this is only for user experience; real protection must happen on the Express API by verifying tokens on every request.
26
Write a register endpoint that hashes the password with bcrypt.
Three services on one network:
services:
mongo:
image: mongo:8
volumes:
- mongo-data:/data/db
api:
build: ./server
environment:
MONGO_URI: mongodb://mongo:27017/shop
JWT_SECRET: dev-secret
ports:
- "5000:5000"
depends_on:
- mongo
web:
build: ./client
ports:
- "8080:80"
depends_on:
- api
volumes:
mongo-data:
The API reaches the database through the service name mongo.
28
Write a Mongoose schema for a user with validation and timestamps.
The aggregation pipeline processes documents through a sequence of stages, each transforming the stream. Common stages are $match to filter, $group to aggregate with operators like $sum and $avg, $project or $addFields to shape fields, $sort, $limit, $skip, $lookup to join another collection, $unwind to flatten arrays and $facet for multiple outputs. Put $match and $sort early so they can use indexes and reduce the data volume.
30
Tell me about a time you improved the performance of a slow database-driven feature.
Situation: our admin orders page took 8 seconds to load. Task: I was asked to fix it within a sprint. Action: I profiled the API, found a populate on every row plus an unindexed sort, added a compound index, replaced populate with a single $lookup projecting only needed fields, and used lean. Result: load time dropped below 600 ms and I shared an indexing checklist with the team.
31
How should a component display data loaded from an API in a user-friendly way?
Handle every state explicitly: show a skeleton or spinner while loading, an error message with a retry button if the request fails, an empty state with guidance when there is no data, and the content otherwise. Keep these in state variables or use a library like TanStack Query that provides isPending, isError and data. Never leave a blank screen or crash on undefined data.
32
Explain indexes in MongoDB, compound indexes and the ESR rule.
An index is a sorted structure that lets queries avoid scanning every document. A compound index covers multiple fields in order, like { userId: 1, createdAt: -1 }, and supports queries on its leading prefix. The ESR guideline says order fields as Equality first, then Sort, then Range. Indexes speed reads but slow writes and use memory, so create them for real query patterns and drop unused ones.
33
Why does React need keys in lists, and why is using the array index risky?
Keys tell React which list item is which between renders, so it can reuse, move or remove the correct DOM nodes and component state. Use stable unique ids, such as a MongoDB _id. Index keys break when items are inserted, removed or reordered: state such as input text or checkbox values can attach to the wrong item, and rendering becomes less efficient. Indexes are acceptable only for static lists.
34
How do you set up npm scripts for development and production in a Node.js API?
Define scripts in package.json and run them with npm run.
"scripts": {
"dev": "node --watch --env-file=.env src/server.js",
"start": "node src/server.js",
"lint": "eslint .",
"test": "vitest run"
}
Modern Node has a built-in --watch flag, so nodemon is optional. npm start and npm test work without the run keyword.
React.memo wraps a component so it skips re-rendering when its props are shallowly equal to the previous props. It helps with expensive components that re-render often because the parent re-renders, such as rows in a large table. It fails if you pass new object, array or function props every render, so pair it with useMemo and useCallback. Measure with React DevTools Profiler before adding it.
36
Write a production Dockerfile for a Node.js Express API.
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.
37
How does the useEffect dependency array work and why is cleanup important?
useEffect runs after render. With no array it runs after every render, with an empty array only after mount, and with dependencies whenever any of them change by Object.is comparison. The function you return is the cleanup, which runs before the next effect and on unmount. Use it to remove listeners, clear intervals, abort requests and close sockets, otherwise you get leaks and duplicate subscriptions.
38
Write a React Testing Library test for a counter button.
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.
39
Every time a user types in an input inside a list item, the input loses focus. What could be the cause?
The component is likely being remounted on each render. Common causes are generating keys randomly, such as key={Math.random()}, defining a component inside another component's body so it gets a new identity every render, or using index keys while the list reorders. Use stable ids as keys and move inner component definitions to the module level so React preserves their DOM and state.
40
Users must upload files up to 200 MB. How would you handle this in a MERN application?
Avoid buffering big files in the API server's memory. The best approach is to have the backend generate a pre-signed URL for object storage such as S3, then let the React client upload directly to storage, with multipart upload for large files. If uploads must go through Express, use multer with disk storage or stream to storage, enforce size and type limits, and save only metadata in MongoDB.
Frequently asked questions
What is asked in MERN Stack interviews for 1 year of experience?
With one year of experience, interviewers expect you to have shipped real features. They ask about your daily work, how you fetch and manage data in React, how you structure Express projects, validation, error handling and JWT authentication. Expect practical tasks like writing middleware, a custom hook or an aggregation, plus questions on Git workflow, code reviews and debugging bugs reported by QA.
How many questions should I practise before a MERN Stack interview?
Work through all 40 questions here, then the company-wise sets for the employers you are targeting. Quality matters more than count: be able to explain why each answer is right.
Which topics matter most for 1 year of experience?
Focus first on Feature delivery, Custom hooks, API structure and validation, Debugging.