Ace Your Interviews 🎯
Browse our collection of interview questions across various technologies.
What is Express.js and why use it over raw Node.js http module?
Express is a minimal web framework for Node.js that adds routing, middleware, and utilities. The raw http module requires manual URL parsing, method checking, and body reading. Express wraps all of that — a route that takes 30 lines raw takes 3 in Express.
What is middleware in Express?
A function with (req, res, next) signature that executes during the request-response cycle. Middleware can modify req/res, end the request, or call next() to pass control to the next middleware.
What is the difference between app.use() and app.get()?
app.use() matches any HTTP method and any path starting with the specified prefix — used for middleware. app.get() only matches GET requests to the exact path — used for route handlers.
What are req.params, req.query, and req.body?
req.params: named route parameters (/users/:id). req.query: URL query string values (?page=2&limit=10). req.body: data in the request body (requires express.json() middleware to parse).
What does express.json() do?
It's built-in middleware that parses incoming requests with JSON Content-Type headers and makes the parsed data available on req.body. Without it, req.body is undefined.
What HTTP status codes should a REST API return for these scenarios: success, created, bad input, unauthorized, not found, server error?
200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error. Correct status codes are part of API design fundamentals.
What is Express Router?
A mini Express application — it has its own routes and middleware and can be mounted on the main app with app.use('/prefix', router). Used to organize routes into separate files by resource.
How do you serve static files in Express?
With the built-in express.static() middleware: app.use(express.static('public')). Any file in the 'public' folder is served directly — HTML, CSS, images, client-side JS.
What is CORS and how do you fix it in Express?
Cross-Origin Resource Sharing — a browser security policy that blocks requests from a different origin. Fix with the 'cors' npm package: app.use(cors({ origin: 'https://yourfrontend.com' })).
How do you read environment variables in an Express app?
Use the dotenv package: require('dotenv').config() at the top of app.js. Then access variables with process.env.VARIABLE_NAME. Never hardcode secrets — store them in .env and add .env to .gitignore.
What is the difference between application-level and route-level middleware?
Application-level: registered with app.use() — runs for all routes. Route-level: passed as arguments to a specific route handler — runs only for that route. Example: app.get('/admin', authMiddleware, adminHandler).
How do you handle errors in async Express route handlers?
Wrap in try/catch and call next(err) to pass to the error-handling middleware. In Express 5 (stable in 2024+), async errors are caught automatically. In Express 4, try/catch is mandatory or use the express-async-errors package.
What is the error-handling middleware signature and why does it matter?
It must have exactly 4 parameters: (err, req, res, next). Express identifies error-handling middleware by parameter count. With 3 parameters, Express treats it as regular middleware and won't route errors to it.
How would you implement JWT authentication in Express?
On login, sign a JWT with user data and secret: jwt.sign({id: user._id}, secret, {expiresIn: '7d'}). On protected routes, middleware extracts the token from Authorization header, verifies it with jwt.verify(), attaches user to req.user, calls next().
What is the difference between PUT and PATCH in REST APIs?
PUT replaces the entire resource. PATCH applies a partial update — only the fields sent are changed. For updating a user's name only, PATCH is semantically correct. Most teams use PUT for simplicity in smaller APIs.
How do you implement pagination in an Express + MongoDB API?
Accept page and limit as query params. Calculate skip = (page - 1) * limit. Use Model.find().skip(skip).limit(limit). Return total document count alongside results so the client knows total pages.
How do you secure an Express API?
Use helmet (security headers), cors (restrict origins), express-rate-limit (prevent brute force), mongo-sanitize (prevent NoSQL injection), validate all inputs with express-validator, use HTTPS, never expose stack traces in production.
What is express-validator and when would you use Joi instead?
express-validator: middleware-based, integrates directly into Express route definitions. Joi: schema-based, validation logic defined separately. Both work well — Joi is preferred in NestJS-style codebases and for complex nested schemas.
What is Multer and how does it handle file uploads?
Multer is middleware for handling multipart/form-data (file uploads). It parses the request, applies file filters and size limits, and makes the file(s) available on req.file (single) or req.files (multiple). Configure storage as disk or memory.
How do you version an Express API?
Mount different routers on versioned prefixes: app.use('/api/v1', v1Router), app.use('/api/v2', v2Router). V2 can add new routes and deprecate old ones without breaking existing v1 clients.
How would you implement rate limiting in Express and why is it important?
Use express-rate-limit: limit requests per IP per time window. Without it, a single user can hammer your API with thousands of requests — brute-forcing passwords, scraping data, or causing DoS. Apply stricter limits to auth routes.
What is the difference between session-based and token-based (JWT) authentication?
Sessions: server stores session data, client holds session ID in cookie — stateful, requires shared storage (Redis) for horizontal scaling. JWT: server is stateless, all data in the token — scales horizontally but token revocation requires a blocklist.
How would you implement token refresh in a JWT auth system?
Issue two tokens: short-lived access token (15 min) and long-lived refresh token (7 days) stored in httpOnly cookie. When access token expires, client calls /api/auth/refresh — server verifies refresh token, issues new access token without requiring re-login.
How do you test an Express API?
Use Jest as the test runner with Supertest to make HTTP requests against your Express app. Create a separate test database. Write unit tests for middleware and controllers, integration tests for full request-response cycles. Mock external services.
What is a webhook and how do you handle one in Express?
A webhook is an HTTP POST that an external service sends when an event occurs (e.g., Stripe sends payment.succeeded). In Express, define a POST route for the webhook URL. Verify the webhook signature from the header before processing to prevent spoofing.
How would you implement caching in an Express API?
Use Redis. Before querying the DB, check Redis for cached data. On cache miss, query DB, store result in Redis with a TTL, return to client. On mutations, invalidate the relevant cache keys. Reduces DB load dramatically for frequently-read data.
What is helmet and what does it protect against?
Helmet sets various HTTP security headers: Content-Security-Policy (XSS), X-Frame-Options (clickjacking), HSTS (forces HTTPS), X-Content-Type-Options (MIME sniffing). One app.use(helmet()) adds a layer of protection against common web attacks.
How do you handle database transactions in Express with MongoDB?
Use Mongoose sessions: const session = await mongoose.startSession(); session.startTransaction(). Pass { session } to all operations in the transaction. On success: session.commitTransaction(). On error: session.abortTransaction(). Requires MongoDB replica set.
What is graceful shutdown and how do you implement it in Express?
Listen for SIGTERM/SIGINT signals. Stop accepting new connections (server.close()), finish in-flight requests, close DB connections, then process.exit(). Prevents data corruption during Kubernetes rolling updates or PM2 restarts.
How do you implement multipart file upload to AWS S3 instead of disk in Express?
Use multer with memoryStorage (stores file in buffer, not disk). In the route handler, use AWS SDK v3's PutObjectCommand with the buffer from req.file.buffer. Return the S3 object URL. This is the production pattern — never save to server disk.