Chapter 13 of 13
Top 45 Express Interview Questions
Routing, middleware, request/response handling, error handling, security, and database integration - organized by topic and difficulty, with explanations that go beyond a one-line definition and a code example for each one. Search or filter to find what you need, and share a direct link to any question.
Showing 45 of 45 questions
The first 15 of 45 questions are free to read. Sign up free to unlock every answer and track your progress.
Unlock all 45Express is a minimal web framework built on top of Node's built-in http module. It adds routing, middleware, and convenience methods for requests and responses, without hiding the underlying Node.js server. A common mistake is treating Express as a separate runtime from Node.js - it is simply a library that runs inside a normal Node.js process. Reach for Express when you want structured routing and middleware without a heavier, more opinionated framework.
Example
const express = require('express');
const app = express();
app.get('/', (req, res) => res.send('Hello Express'));
app.listen(3000);Call express() to get an app object, register routes and middleware on it, then call app.listen(port, callback) to start listening for connections. A common mistake is forgetting to call app.listen() at all (the server never starts) or hardcoding the port instead of reading it from process.env.PORT, which breaks on hosting platforms that assign their own port. Always fall back to a default port with process.env.PORT || 3000.
Example
const express = require('express');
const app = express();
app.listen(process.env.PORT || 3000, () => {
console.log('Server started');
});The app object, returned by calling express(), is the central object of an Express program - it is where you register routes, attach middleware, configure settings, and ultimately start the underlying HTTP server. A common mistake is creating multiple app instances unintentionally (for example in tests) and being confused about which one a route was registered on. In most apps there should be exactly one app object, created once and exported from a single module.
Raw http.createServer() gives you a single callback that must manually parse the URL, check the method, read the body, and set headers for every request. Express adds declarative routing (app.get/post/etc.), a middleware pipeline for cross-cutting concerns, and response helpers like res.json() and res.status(). A common mistake is assuming Express replaces Node - it is a thin, additive layer, and you can still reach into the underlying req/res objects (which are Node's own) at any time.
Express does not mandate a project structure, ORM, templating engine, or authentication approach - it provides a small routing and middleware core and leaves everything else to the ecosystem of npm packages and the developer's own conventions. A common mistake is expecting Express to include things larger frameworks bundle by default, like validation or an ORM, and being surprised when a fresh app has none of that wired up. Plan on adding the pieces you need (body parsing, validation, a database layer) explicitly.
Express walks its internal stack of middleware and routes in the exact order they were registered, checking each one for a method and path match, and runs the first one that matches (for routes) or every middleware whose path prefix matches, in order. A common mistake is assuming routes are matched by "best" or "most specific" match rather than "first" match, which causes bugs when a broad dynamic route is registered before a narrower static one. Always register more specific routes before more general ones that could shadow them.
Express exposes a method on the app object for each HTTP verb - app.get(), app.post(), app.put(), app.patch(), app.delete() - each taking a path and one or more handler functions. A route only matches when both the method and the path match, so the same path can have entirely separate handlers per verb. A common mistake is defining a route with app.get() and then wondering why a POST request to the same path returns a 404 - each method needs its own registration.
Example
app.get('/items', (req, res) => res.json([]));
app.post('/items', (req, res) => res.status(201).json({ created: true }));Route parameters are named, colon-prefixed segments of a path (like /users/:id) that match any value in that position of the URL, made available on req.params keyed by name. A common mistake is forgetting that route parameters are always strings, even for numeric-looking segments, which can cause subtle bugs when comparing req.params.id === 5 (a number) instead of using Number() first.
Example
app.get('/users/:id', (req, res) => {
res.json({ id: req.params.id, type: typeof req.params.id });
});
// GET /users/42 -> { id: '42', type: 'string' }Route parameters (req.params) are part of the URL path and typically identify a specific resource, like /orders/:id. Query parameters (req.query) come after the ? in the URL and are meant for optional filtering, sorting, or pagination, like /orders?status=shipped. A common mistake is using a query parameter to identify a resource (e.g. /orders?id=5) when a route parameter would be more RESTful and cacheable, or vice versa, cramming filter options into the path.
Example
app.get('/orders/:id', (req, res) => res.json({ id: req.params.id }));
app.get('/orders', (req, res) => res.json({ status: req.query.status }));
// GET /orders/5 -> route param
// GET /orders?status=shipped -> query paramapp.route(path) returns a chainable route object, letting you attach .get(), .post(), .put(), and .delete() handlers for the same path in one grouped statement, instead of repeating the path string in several separate app.METHOD calls. A common mistake is thinking app.route() changes matching behavior - it is purely an organizational shorthand with the exact same runtime behavior as separate calls.
Example
app.route('/tasks/:id')
.get((req, res) => res.json({ id: req.params.id }))
.delete((req, res) => res.status(204).end());Appending a ? after the parameter name in the path, like /reports/:year/:month?, makes that segment optional so the same handler matches both with and without it. A common mistake is forgetting the parameter still exists as a key on req.params when omitted - its value is just undefined - so handlers should explicitly check for that rather than assuming its absence entirely.
Example
app.get('/reports/:year/:month?', (req, res) => {
res.json({ year: req.params.year, month: req.params.month || 'all' });
});Express matches routes in the order they were registered and stops at the first one that matches, so a dynamic route like /tasks/:id, if registered first, will match a request meant for a more specific static route like /tasks/new, since :id happily matches the literal string "new". A common mistake is assuming Express picks the "best" match; instead, always register more specific static routes above broader dynamic ones on the same path prefix.
Example
// Wrong order - /tasks/new never reached
app.get('/tasks/:id', (req, res) => res.json({ id: req.params.id }));
app.get('/tasks/new', (req, res) => res.send('New task form'));
// Correct order
app.get('/tasks/new', (req, res) => res.send('New task form'));
app.get('/tasks/:id', (req, res) => res.json({ id: req.params.id }));Middleware is a function with the signature (req, res, next) that sits in the request-handling pipeline: it can inspect or modify req/res, run arbitrary code, and then either call next() to pass control along or send a response to end the cycle. A common mistake is forgetting to call next() (or send a response), which leaves the request hanging with no reply ever sent.
Example
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});app.use(middlewareFn) registers middleware that runs for every incoming request regardless of method, before any route is matched. A common mistake is registering global middleware after the routes that need it (like body-parsing after a route that reads req.body), since Express only applies middleware to requests that reach it after it was registered.
Example
app.use(express.json()); // must come before routes that read req.body
app.post('/echo', (req, res) => res.json(req.body));The request simply hangs - Express has no built-in timeout for a middleware that does nothing, so the client eventually times out waiting for a reply. A common mistake is writing a conditional inside middleware where one branch calls next() but another (perhaps an early return meant to fail the request) forgets to send a response or call next(err), silently stalling the request instead of failing fast.