95 Express Interview Questions and Answers (2026)

Blog / 95 Express Interview Questions and Answers (2026)
Express interview questions and answers

Express still runs a huge share of production Node.js APIs, and interviewers know it. As systems scale and the bar rises, they're no longer satisfied with "I've used it"—they want to see you reason about middleware order, route matching, and error handling on the spot. Walk in shaky on the fundamentals and it shows fast.

This guide gives you 95 questions with concise, interview-ready answers and code where it actually helps. It's structured Junior to Mid to Senior, so you build from routing and req/res basics up to security, modular routers, and migration gotchas. Work through it and you'll speak about Express like someone who's shipped with it.

Q1.
What is the difference between req.params, req.query, and req.body, and when would you use each?

Junior

They read data from three different parts of the request: req.params holds named route segments, req.query holds the URL query string, and req.body holds the parsed request payload.

  • req.params: route path variables:

    • Comes from named segments like /user/:id giving req.params.id.

    • Use for identifying a specific resource.

  • req.query: parsed query string:

    • From ?sort=asc&page=2 giving req.query.sort.

    • Use for optional filtering, sorting, pagination.

  • req.body: parsed request payload:

    • Requires body-parsing middleware like express.json() or express.urlencoded(); undefined otherwise.

    • Use for data sent in POST/PUT requests, like form or JSON bodies.

Q2.
How do you define optional parameters in an Express route path?

Junior

You mark a route parameter as optional by appending a ? to it, meaning the route matches whether or not that segment is present.

  • Syntax: /user/:id? matches both /user and /user/42.

  • Access and defaults: When omitted, req.params.id is undefined, so guard or provide a default.

  • Version note: The :param? form works in Express 4 (via path-to-regexp); Express 5 changed the syntax, so confirm the version.

javascript

app.get('/user/:id?', (req, res) => { res.send(req.params.id ? `User ${req.params.id}` : 'All users'); });

Q3.
Explain the signature of an Express middleware function. What do req, res, and next represent?

Junior

A standard Express middleware is a function taking (req, res, next): the request object, the response object, and a callback that hands control to the next middleware in the stack.

  • req: The incoming HTTP request: holds req.params, req.query, req.body, headers, and any properties earlier middleware attached.

  • res: The outgoing response: used to end the cycle with res.send(), res.json(), res.status(), etc.

  • next: A function that passes control onward; next(err) skips to error-handling middleware.

  • Error-handling variant: Takes four args, (err, req, res, next); Express identifies it by arity.

Q4.
What happens if you forget to call next() in a middleware function that doesn't end the request-response cycle?

Junior

The request hangs: control never advances past that middleware, so no further handler runs and no response is sent, leaving the client waiting until it times out.

  • The pipeline stalls:

    • Express only moves to the next middleware when you call next() or end the response.

    • Doing neither means the request is stuck indefinitely.

  • Two valid ways to satisfy the contract:

    • End the cycle with a response method like res.send(), or

    • Call next() to defer to the next handler.

  • Common cause: A forgotten next() inside an async branch or after a conditional, so some code paths never respond.

Q5.
Explain the (req, res, next) signature. What is the purpose of the next function, and what happens to the request if it is never called?

Junior

The (req, res, next) signature is Express's middleware contract; next is the function that yields control to the next middleware or route, and if it is never called (and no response is sent) the request hangs forever.

  • Purpose of next:

    • Advances the pipeline so the next matching middleware/route runs.

    • next(err) jumps directly to error-handling middleware, skipping normal handlers.

    • Special tokens: next('route') skips the remaining handlers of the current route, and next('router') exits the router entirely.

  • If next is never called: No downstream handler executes; unless the middleware itself sent a response, the client waits until timeout.

  • Golden rule: Every request path must either end the response or call next(), exactly once.

Q6.
What are the built-in middleware functions provided by Express 4.x/5.x, such as express.json?

Junior

Express bundles a small set of built-in middleware for common tasks like body parsing and static file serving; most other functionality lives in separate packages.

  • express.json(): Parses incoming requests with JSON payloads into req.body (based on body-parser).

  • express.urlencoded(): Parses URL-encoded form bodies (e.g. HTML form posts) into req.body.

  • express.static(): Serves static assets (HTML, images, CSS) from a directory.

  • express.Router(): A mini-app for modular route grouping (technically a factory, not middleware, but built-in).

  • express.raw() / express.text(): Parse raw Buffer or plain-text bodies respectively.

  • Note on history: Older middleware like bodyParser and cookieParser were removed in Express 4 and became separate packages; parsers were later re-added as built-ins.

Q7.
How can you attach multiple middleware functions to a single route, and in what order do they execute?

Junior

You attach multiple middleware to a route by passing them as additional arguments (or an array) before the final handler; they execute left-to-right in the order listed, each calling next() to advance.

  • Syntax options:

    • As separate arguments: app.get('/x', a, b, handler).

    • As an array: app.get('/x', [a, b], handler).

  • Execution order: Strictly sequential in declaration order; each must call next() to reach the next, or send a response to stop.

  • Typical use: Chain concerns like validate then authorize then handle, keeping each middleware single-purpose.

javascript

app.post('/orders', authenticate, validateOrder, (req, res) => { res.json({ ok: true }); }); // runs: authenticate -> validateOrder -> handler

Q8.
How do you pass data from one middleware to the next in the request-processing pipeline?

Junior

You pass data forward by attaching properties to the req object (or res.locals), which persists for the lifetime of that request across all downstream middleware and handlers.

  • Attach to req:

    • e.g. req.user = decodedToken; the next middleware reads req.user.

    • Preferred for request-scoped state like authenticated user or parsed data.

  • res.locals: Also request-scoped but conventionally for data exposed to views/templates during rendering.

  • Best practices: Namespace custom fields to avoid clobbering Express internals; don't store data in module-level or global variables (shared across requests, unsafe).

javascript

function loadUser(req, res, next) { req.user = { id: 42, role: 'admin' }; next(); } app.get('/me', loadUser, (req, res) => res.json(req.user));

Q9.
What is the difference between res.send(), res.json(), and res.end()? When would you use res.end() specifically?

Junior

All three end a response, but they differ in what they do to the body and headers: res.send() is the smart general-purpose method, res.json() forces JSON serialization, and res.end() is the raw Node method that ends the stream with no content-type magic.

  • res.send():

    • Accepts a string, Buffer, object, or array; it infers and sets Content-Type and Content-Length automatically.

    • Objects/arrays are auto-converted to JSON.

  • res.json(): Always serializes to JSON and sets Content-Type: application/json, even for values like null or a number.

  • res.end(): Comes from Node's http.ServerResponse; it ends the response without setting a content-type or serializing.

  • When to use res.end(): To end a response with no body, e.g. res.status(204).end(), or after manually streaming/writing data.

Q10.
Explain the difference between res.render() and res.sendFile().

Junior

res.render() compiles a template through a view engine and sends the resulting HTML, while res.sendFile() streams a file straight from disk to the client with no processing.

  • res.render(view, locals):

    • Looks up a template in the configured views directory and renders it with a view engine (pug, ejs), passing locals as data.

    • Output is generated HTML; sets Content-Type: text/html.

  • res.sendFile(path):

    • Sends a static file as-is (image, PDF, pre-built HTML), guessing Content-Type from the extension.

    • Requires an absolute path (or a root option) and supports range requests / caching headers.

  • Rule of thumb: dynamic, data-driven markup uses render(); static assets use sendFile().

Q11.
How does res.status() chaining work, and what is the difference between res.status(404).send() and res.sendStatus(404)?

Junior

res.status() just sets the status code and returns the response object so you can chain a body method; res.sendStatus() sets the code and immediately sends its textual name as the body.

  • res.status(code):

    • Returns res, enabling res.status(404).send('Not found') or .json(...).

    • You control the body fully.

  • res.sendStatus(code):

    • Sets the code and sends the standard reason phrase as the body, so res.sendStatus(404) sends "Not Found".

    • It ends the response, so you can't chain a custom body onto it.

  • Use status() when you need a custom payload; use sendStatus() for a quick bare status reply.

Q12.
How do you implement a catch-all 404 handler in Express?

Junior

A catch-all 404 handler is a middleware placed after all your routes with no path (or '*'): if no route matched, execution falls through to it, and you respond with a 404.

  • Order matters: Register it last, after every route and router, so it only runs when nothing else handled the request.

  • It has no path pattern: A middleware like app.use((req, res) => ...) matches any method and URL that reached it.

  • Distinct from the error handler: A 404 is not an error; it is simply an unmatched route. Send the response directly, or call next() with an error only if you want the error handler to format it.

javascript

// after all routes app.use((req, res, next) => { res.status(404).json({ error: 'Not Found', path: req.originalUrl }); });

Q13.
What is the x-powered-by header, and why is it a security best practice to disable it using app.disable('x-powered-by')?

Junior

The X-Powered-By header is a response header Express adds by default advertising that the app runs on Express. Disabling it with app.disable('x-powered-by') removes a hint that attackers can use to fingerprint your stack and target known framework vulnerabilities.

  • What it reveals: Sends X-Powered-By: Express on responses, disclosing your framework.

  • Why disable it:

    • Security by obscurity: it gives no functional benefit but helps attackers narrow down known exploits.

    • Reduces your attack surface's information leakage with essentially zero cost.

  • How to disable: Call app.disable('x-powered-by'), or use helmet(), which removes it automatically among other hardening.

Q14.
What is the purpose of the app.set() and app.get() methods for application configuration?

Junior

app.set(name, value) and app.get(name) are a simple key/value store for application-level settings: set stores a configuration value and get retrieves it. Some keys are recognized by Express itself; others are just your own custom settings.

  • Built-in settings: Keys like 'view engine', 'views', 'trust proxy', and 'env' change how Express behaves.

  • Custom settings: Store your own config, e.g. app.set('port', 3000), and read it anywhere you have the app.

  • Naming caution: app.get(name) with one argument reads a setting; app.get(path, handler) with a route defines a GET route: Express distinguishes by the arguments.

javascript

app.set('port', process.env.PORT || 3000); const port = app.get('port'); app.listen(port);

Q15.
What does app.set('view engine', ...) and app.set('views', ...) configure, and how does Express locate and render templates?

Junior

app.set('view engine', ...) sets the default template engine (so you can omit file extensions), and app.set('views', ...) sets the directory where template files live. Together they let res.render() find and compile a template into HTML.

  • 'view engine': Names the default engine, e.g. 'pug' or 'ejs'; lets you call res.render('home') without the extension.

  • 'views': The folder (or array of folders) Express searches for template files; defaults to ./views.

  • How rendering works:

    1. res.render('home', data) resolves the file: views/home.pug.

    2. Express loads the registered engine for that extension and compiles the file.

    3. It merges app.locals, res.locals, and data, then sends the resulting HTML.

  • Engine registration: Popular engines self-register when installed; otherwise use app.engine() to map an extension to a render function.

javascript

app.set('view engine', 'pug'); app.set('views', path.join(__dirname, 'views')); app.get('/', (req, res) => { res.render('home', { title: 'Hi' }); // renders views/home.pug });

Q16.
How can you set or clear cookies using the Express response object?

Junior

Use res.cookie(name, value, options) to set a cookie and res.clearCookie(name, options) to remove one. Both write a Set-Cookie header, so they must run before the response is sent.

  • Setting: res.cookie('token', abc, { httpOnly: true }) adds a Set-Cookie header the browser stores.

  • Clearing: res.clearCookie('token') sends a Set-Cookie with an expired date so the browser drops it.

  • Options must match to clear: path and domain used in clearCookie must match those used when the cookie was set, or it won't be removed.

  • Timing: Call them before res.send()/res.json(), since headers can't change after the body starts.

javascript

res.cookie('token', 'abc123', { httpOnly: true, maxAge: 3600000 }); res.clearCookie('token');

Q17.
What is the purpose of the cookie-parser middleware, and how does it populate req.cookies?

Junior

cookie-parser is middleware that reads the incoming Cookie header, parses it into a key/value object, and attaches it to req.cookies so handlers can read cookies without manual string parsing.

  • What it does: Parses the Cookie request header once per request and populates req.cookies.

  • Signed cookies: Pass a secret (cookieParser('secret')) and verified signed cookies appear on req.signedCookies instead.

  • Order: Register it before any route that reads cookies, since middleware runs top-down.

  • Note: It only reads cookies; setting them still uses res.cookie() (built into Express).

javascript

const cookieParser = require('cookie-parser'); app.use(cookieParser('my-secret')); app.get('/', (req, res) => { console.log(req.cookies.token); // unsigned console.log(req.signedCookies.session); // verified signed });

Q18.
What does req.xhr indicate, and how might you use it inside a route handler?

Junior

req.xhr is a boolean that is true when the request's X-Requested-With header equals XMLHttpRequest, which older AJAX libraries (like jQuery) set. It's a heuristic for distinguishing AJAX calls from full page loads.

  • What it checks: Only reflects the X-Requested-With header, nothing more.

  • Typical use: Return JSON to AJAX clients but render an HTML page or redirect for normal browser navigation.

  • Caveat: Modern fetch() does not set that header by default, so req.xhr is unreliable now; prefer real content negotiation via the Accept header.

javascript

app.get('/items', (req, res) => { if (req.xhr) return res.json(items); res.render('items', { items }); });

Q19.
What is the difference between req.get() (req.header()) and accessing req.headers directly?

Junior

req.get() (aliased as req.header()) is a helper method for reading a single header case-insensitively with some special handling, whereas req.headers is the raw object of all headers with lowercased keys.

  • req.get(name):

    • Case-insensitive: req.get('Content-Type') and req.get('content-type') both work.

    • Special aliases: 'Referrer' and 'Referer' are treated the same.

    • Returns undefined if the header is absent.

  • req.headers:

    • The raw Node object; keys are always lowercase, so you must match exactly.

    • No aliasing or convenience logic; just a plain property lookup.

  • Rule of thumb: Prefer req.get() for reading a header; use req.headers when iterating over all of them.

Q20.
What is the difference between next() and next('route')?

Mid

Both control middleware flow, but next() moves to the next matching handler in the stack, while next('route') skips the rest of the handlers for the current route and jumps to the next matching route.

  • next(): pass control forward:

    • Invokes the next middleware or route handler in sequence.

    • Passing a value (except the string 'route') is treated as an error and jumps to error-handling middleware, e.g. next(err).

  • next('route'): skip remaining handlers on this route:

    • Only works within handlers defined via app.METHOD() or router.METHOD() that have multiple callbacks.

    • Useful to bail out of a chain early and let another matching route try.

javascript

app.get('/user/:id', (req, res, next) => { if (req.params.id === '0') return next('route'); // skip to next route next(); // continue to the handler below }, (req, res) => res.send('regular user')); app.get('/user/:id', (req, res) => res.send('special user 0'));

Q21.
What are the advantages of using express.Router() over defining all routes directly on the app object? How does it help with application mounting?

Mid

express.Router() creates a modular, mountable mini-application: you group related routes and middleware into a separate file, then attach the whole group to the app at a base path, keeping the code organized and reusable.

  • Modularity and organization: Split routes by feature (users, orders) into their own files instead of one giant app file.

  • Scoped middleware: router.use() applies middleware only to routes on that router, not the whole app.

  • Clean mounting with a base path:

    • app.use('/users', usersRouter) prefixes every route in the router, so route files stay path-agnostic.

    • Changing the prefix is a one-line edit at the mount point.

  • Reusability: The same router can be mounted at multiple paths or across apps.

javascript

// users.js const router = express.Router(); router.get('/', listUsers); router.get('/:id', getUser); module.exports = router; // app.js app.use('/users', require('./users')); // /users and /users/:id

Q22.
How does Express handle route matching when multiple paths could match a request (e.g., /user/:id vs. /user/profile)? Does the order of definition matter?

Mid

Express matches routes in the order they are defined, top to bottom, and runs the first one that matches. Order absolutely matters: a dynamic route like /user/:id will capture /user/profile if it is declared first, so more specific routes must come before more general ones.

  • First match wins: Express walks the middleware/route stack sequentially and stops at the first handler that matches and sends a response.

  • Dynamic segments are greedy for their position: /user/:id matches any single segment, including profile, so it would treat profile as an id.

  • Define specific before general: Put /user/profile above /user/:id so the literal path is checked first.

  • next() lets you fall through: A matching handler can call next() to let later matching routes also run.

javascript

app.get('/user/profile', getProfile); // specific first app.get('/user/:id', getUser); // dynamic second

Q23.
Explain the difference between app.use() and app.all() when defining routes.

Mid

app.use() mounts middleware that matches a path prefix for any HTTP method, while app.all() registers a route handler that matches the exact path for every HTTP method.

  • app.use(): prefix-based middleware:

    • Matches the path and everything under it, e.g. app.use('/api') matches /api/users too.

    • Path is optional (defaults to /); designed for cross-cutting logic like logging or auth.

  • app.all(): exact-path, all-methods route:

    • Matches the path exactly (using route pattern matching), not as a prefix.

    • Behaves like app.get/app.post but for any verb; good for path-specific checks across methods.

  • Rule of thumb: Use app.use() for middleware over a section of the app; use app.all() to handle one endpoint regardless of method.

Q24.
What is the purpose of app.route()? How does it help reduce redundancy when handling multiple HTTP methods for the same path?

Mid

app.route() returns a single route instance for a given path so you can chain handlers for different HTTP methods, avoiding repeating the path string across separate declarations.

  • Single point of definition: Declares the path once, then attaches .get(), .post(), .put() via chaining.

  • Reduces redundancy and typos: No repeated '/book' strings that can drift out of sync.

  • Groups related logic: All method handlers for one resource sit together, improving readability.

javascript

app.route('/book') .get((req, res) => res.send('get a book')) .post((req, res) => res.send('add a book')) .put((req, res) => res.send('update the book'));

Q25.
What is the purpose of app.param() middleware?

Mid

app.param() registers middleware that runs whenever a specific route parameter appears in a matched route, letting you centralize logic like loading or validating that parameter once instead of repeating it in every handler.

  • Triggered by parameter name: app.param('id', fn) runs fn for any route containing :id, before its handlers.

  • Callback signature: Receives (req, res, next, value) where value is the parameter's value.

  • Common uses: Fetch a resource once and attach it (e.g. req.user), or validate and reject invalid values early.

  • Runs once per request: Even if the parameter appears in multiple matched layers, the callback fires once per request.

javascript

app.param('id', async (req, res, next, id) => { const user = await db.findUser(id); if (!user) return res.status(404).send('Not found'); req.user = user; // available to all /:id handlers next(); }); app.get('/user/:id', (req, res) => res.json(req.user));

Q26.
How does Express match route paths? Explain the difference between string paths, path patterns, and regular expressions.

Mid

Express matches an incoming path against each route's pattern in registration order, using the path-to-regexp library to compile whatever you pass into a regular expression internally.

  • String paths (exact/literal):

    • A plain string like /users matches that exact path (query string ignored).

    • Simplest and most common form.

  • String path patterns:

    • Strings can use special characters compiled by path-to-regexp: ? (optional), + (one or more), * (wildcard), and () groups.

    • Example: /ab?cd matches /acd and /abcd.

  • Regular expressions:

    • Pass an actual RegExp for full control: app.get(/.*fly$/, ...) matches any path ending in fly.

    • The regex is tested against the path, not anchored automatically the way string patterns are.

  • Note: Express 5 changed path matching (dropped some path-to-regexp wildcard behavior), so * and unnamed patterns behave differently across major versions.

Q27.
What is the difference between req.path, req.originalUrl, and req.baseUrl in Express?

Mid

These three properties describe different slices of the requested URL, and the differences only become visible once routers are mounted on a sub-path.

  • req.originalUrl: The full original URL as received, including query string; never rewritten by mounting.

  • req.baseUrl: The path prefix on which the current router was mounted (e.g. /api if you did app.use('/api', router)).

  • req.path: The path portion relative to the current handler, without the query string.

  • Relationship: Roughly originalUrl = baseUrl + path + query.

javascript

// mounted: app.use('/api', router) // request: GET /api/users?active=1 router.get('/users', (req, res) => { req.originalUrl; // '/api/users?active=1' req.baseUrl; // '/api' req.path; // '/users' res.end(); });

Q28.
How do route parameters get parsed into req.params, and how do named parameters with regex constraints work?

Mid

Named segments in a route path (prefixed with :) are captured by path-to-regexp and placed onto req.params as string values keyed by the parameter name.

  • How parsing works:

    • A path like /users/:id compiles to a regex with a capture group; on a match, the group's value becomes req.params.id.

    • Values are always strings (e.g. '42'), so cast as needed.

  • Multiple and optional params: /flights/:from-:to captures two params from one segment; :id? makes a param optional.

  • Regex constraints on a param:

    • Append a pattern in parentheses to restrict what matches: /users/:id(\d+) only matches numeric ids.

    • If the constraint fails, the route simply doesn't match and Express moves on.

  • app.param(): Registers a callback that runs when a given param is present, useful for loading/validating a resource once.

javascript

app.get('/users/:id(\\d+)', (req, res) => { const id = Number(req.params.id); // '42' -> 42 res.json({ id }); });

Q29.
How does middleware ordering affect the execution of a request? Provide an example where order matters.

Mid

Middleware runs in the exact order it is registered, forming a top-to-bottom pipeline where each function can modify the request/response or short-circuit the chain, so order determines both behavior and correctness.

  • Sequential pipeline: Each middleware calls next() to pass control to the next one; the first match to end the cycle stops the chain.

  • Setup must come before use: A body parser or auth check must be registered before the routes that depend on it, or those routes see undefined data.

  • Catch-alls come last: Error handlers and 404 handlers must be registered after routes to catch what falls through.

javascript

// WRONG: route runs before body is parsed app.post('/user', (req, res) => res.json(req.body)); // undefined app.use(express.json()); // RIGHT: parser registered first app.use(express.json()); app.post('/user', (req, res) => res.json(req.body)); // parsed

Q30.
What is the difference between application-level middleware and router-level middleware? When would you choose one over the other?

Mid

Application-level middleware is bound to the app instance via app.use() and applies globally, while router-level middleware is bound to an express.Router() instance and applies only to routes within that router.

  • Application-level:

    • Registered with app.use(...) or app.METHOD(...); runs for every matching request across the whole app.

    • Good for cross-cutting concerns: logging, CORS, body parsing, global auth.

  • Router-level:

    • Attached to a Router and mounted with app.use('/prefix', router); scoped to that router's routes.

    • Good for modularizing a feature area and applying middleware only to its routes (e.g. admin-only checks).

  • Choosing: Use application-level for truly global behavior; use router-level to keep concerns and middleware local to a module and avoid leaking them app-wide.

javascript

const router = express.Router(); router.use(requireAdmin); // only /admin routes router.get('/dashboard', handler); app.use('/admin', router);

Q31.
Explain how a middleware can short-circuit the request-response cycle. If a middleware calls res.send(), will subsequent middleware or route handlers still execute?

Mid

A middleware short-circuits the cycle by sending a response (e.g. res.send()) and not calling next(). Once the response is sent and next() is skipped, no subsequent middleware or route handlers run.

  • How short-circuiting works:

    • Express advances the pipeline only when a middleware calls next(). Ending the response instead stops the chain.

    • Common for auth guards, rate limits, or short-circuit caching: reject or serve early.

  • Answer: no, subsequent handlers do NOT execute: Calling res.send() (or res.json(), res.end()) without next() ends the request.

  • The double-send trap: If you send a response AND also call next(), downstream code may try to send again, causing ERR_HTTP_HEADERS_SENT.

javascript

function auth(req, res, next) { if (!req.headers.authorization) { return res.status(401).send('Unauthorized'); // short-circuits, no next() } next(); // continue the pipeline }

Q32.
What is the role of express.static() and why is it often placed at the top of the middleware stack?

Mid

express.static() serves files (images, CSS, JS, HTML) directly from a folder. It's often placed early so static requests are answered immediately without running unnecessary downstream middleware.

  • What it does: Maps a URL path to files on disk and handles caching headers, content types, and ranges.

  • Why place it near the top:

    • Performance: a matched static file responds and short-circuits, skipping auth, logging, or body parsing that assets don't need.

    • If it's the correct request, there's no reason to run more logic.

  • Caveat: If assets need protection (auth), place the guard BEFORE express.static(), otherwise files leak past your checks.

javascript

app.use(express.static('public')); // GET /logo.png serves public/logo.png

Q33.
How does Express use the NODE_ENV variable? What internal optimizations like view caching are enabled when NODE_ENV is set to production?

Mid

Express reads process.env.NODE_ENV to decide whether to enable production optimizations. Setting it to production turns on view template caching and terser error output, improving performance.

  • View caching: In production, compiled view templates are cached in memory instead of re-read and re-compiled on every request.

  • Error handling: The default error handler hides stack traces in production (avoids leaking internals to clients).

  • How it's set:

    • An environment variable, not code: NODE_ENV=production node app.js. If unset, Express treats it as development.

    • Reported to give meaningful performance gains, so it's a standard deployment step.

  • Reuse: Check it in your own code via app.get('env') to branch logging or config.

Q34.
Explain the difference between the Node.js raw http module and Express.

Mid

The raw http module is Node's low-level HTTP server primitive; Express is a framework built on top of it that adds routing, middleware, and convenience helpers so you write less boilerplate.

  • Raw http module:

    • You get a single request handler and must manually parse URLs, dispatch on req.method and req.url, set headers, and write the response.

    • No built-in routing, no middleware pipeline, no body parsing.

  • Express:

    • Adds a routing layer (app.get(), app.post()) and a middleware chain via next().

    • Enriches req/res with helpers like res.json(), res.redirect(), and req.params.

  • Relationship: Express does not replace http: it wraps it. app.listen() ultimately calls http.createServer(app).

Q35.
Why is it considered a best practice to separate your Express app definition from the server.listen() call?

Mid

Separating the app (routes and middleware) from the code that starts the server makes the app importable and testable without opening a real port, and keeps startup concerns decoupled from application logic.

  • Testability: Tools like supertest can import the app object directly and exercise routes in-memory, no listening socket needed.

  • Reusability: The same app can be mounted, run under different servers (HTTP/HTTPS), or run in serverless environments.

  • Clean separation of concerns: Port, TLS, and process setup live in the entry file; routing and business logic live in the app module.

javascript

// app.js const express = require('express'); const app = express(); app.get('/', (req, res) => res.send('ok')); module.exports = app; // server.js const app = require('./app'); app.listen(3000, () => console.log('listening'));

Q36.
What does app.listen() actually do, and how does it relate to Node's http.createServer?

Mid

app.listen() is a thin convenience wrapper: it creates a Node http.Server using the Express app as its request handler and starts it listening on the given port.

  • What it does: Internally it calls http.createServer(app) then server.listen(...) and returns the http.Server instance.

  • Why the app can be passed to createServer: An Express app is itself a function with signature (req, res), which is exactly what http.createServer expects as a handler.

  • When to call createServer yourself: You need direct access to the server object: HTTPS, attaching WebSockets (socket.io), or graceful shutdown handling.

javascript

// These are equivalent: app.listen(3000); const http = require('http'); http.createServer(app).listen(3000);

Q37.
How do you perform a redirect in Express, and what is the difference between res.redirect() and res.location()?

Mid

res.redirect() sends a complete redirect response (a 3xx status plus the Location header, ending the request), while res.location() only sets the Location header and does nothing else.

  • res.redirect():

    • Sets the status (default 302), sets Location, and ends the response.

    • Accepts an optional status: res.redirect(301, '/new'). Supports relative paths and the special 'back' value.

  • res.location():

    • Only sets the Location response header; it does not set a status or terminate the response.

    • Useful when you want Location on a non-redirect response (e.g. 201 Created pointing to the new resource).

  • Relationship: res.redirect() internally uses res.location() plus a status and body.

javascript

res.redirect('/login'); // 302 + Location + ends res.location('/users/42').status(201).json(user); // header only

Q38.
How does the res.format() method work in Express, and how does it help with building APIs that support multiple response types like JSON and HTML?

Mid

res.format() performs content negotiation: it inspects the request's Accept header and runs the handler matching the best content type, letting one route serve different representations of the same resource.

  • How it works:

    • You pass an object keyed by MIME type or shorthand (json, html, text); Express picks the callback matching the client's Accept header.

    • It automatically sets the response Content-Type and adds a Vary: Accept header for correct caching.

  • Fallbacks: A default key handles unmatched types; without it, Express responds 406 Not Acceptable.

  • Why it helps APIs: One endpoint can serve JSON to API clients and HTML to browsers without duplicating routing logic.

javascript

app.get('/users/:id', (req, res) => { const user = getUser(req.params.id); res.format({ 'application/json': () => res.json(user), 'text/html': () => res.render('user', { user }), default: () => res.status(406).send('Not Acceptable'), }); });

Q39.
How does res.redirect() work under the hood in terms of HTTP status codes?

Mid

Under the hood res.redirect() sets a 3xx status code and the Location header telling the browser where to go; it defaults to 302 Found but you can supply any redirect status.

  • Default status: 302 Found: a temporary redirect; the browser follows the Location header to fetch the new URL.

  • Common codes you can pass:

    1. 301 Moved Permanently: permanent; caches and search engines update.

    2. 302 Found / 307 Temporary Redirect: temporary. 307 preserves the original HTTP method and body.

    3. 303 See Other: tells the client to GET the new URL (common after a POST).

  • Mechanism: It writes the status line and Location header, includes a small body (respecting the request's Accept), then ends the response. The redirect itself is entirely driven by the status code and header.

javascript

res.redirect('/home'); // 302 Found, Location: /home res.redirect(301, '/new-url'); // 301 Moved Permanently

Q40.
What happens if you call res.send() and then call next() immediately after?

Mid

The response is sent fine, but calling next() afterward passes control to the next matching handler, which will try to write to an already-finished response and throw ERR_HTTP_HEADERS_SENT.

  • res.send() ends the response: Headers and body are flushed and the response is marked finished (res.headersSent becomes true).

  • next() continues the chain:

    • It does not stop the current function; execution keeps going and the next middleware runs.

    • If that middleware also writes, Node throws "Cannot set headers after they are sent to the client."

  • Fix: return res.send(...) (or simply don't call next()) once you've responded.

Q41.
How do you set response headers in Express using res.set()/res.header(), and how does res.append() differ from res.set()?

Mid

res.set() (aliased as res.header()) sets or replaces a response header, whereas res.append() adds a value without overwriting an existing one.

  • res.set(field, value) / res.header(field, value):

    • Sets one header, or pass an object to set many at once.

    • Replaces any previous value for that field.

  • res.append(field, value):

    • Preserves existing values and adds another, useful for repeatable headers like Set-Cookie or Vary.

    • If the header wasn't set yet, it behaves like set().

javascript

res.set('Content-Type', 'text/html'); res.set({ 'X-Powered-By': 'me', 'Cache-Control': 'no-store' }); res.append('Set-Cookie', 'a=1'); res.append('Set-Cookie', 'b=2'); // two Set-Cookie headers

Q42.
What does res.type() do, and how does Express infer the Content-Type when you use res.send() with different argument types?

Mid

res.type() sets the Content-Type header from a MIME type or extension shortcut, while res.send() auto-infers the type based on the argument's JavaScript type if you haven't set one.

  • res.type(x): Accepts a MIME type (application/json) or a short extension ('html', 'png') and looks it up via mime-types.

  • How res.send() infers type:

    • String: text/html.

    • Buffer: application/octet-stream.

    • Object / array / number / boolean: serialized as JSON with application/json.

  • Inference only applies if Content-Type hasn't already been set, so res.type() or res.set() overrides it.

Q43.
What is res.jsonp() and when would you use it instead of res.json()?

Mid

res.jsonp() sends JSON wrapped in a JavaScript callback function so it can be loaded cross-origin via a <script> tag; use it only for legacy JSONP clients, since CORS is the modern approach.

  • How it works:

    • If the request has a callback query param (default ?callback=), it responds with callbackName({...}) as JavaScript.

    • Without a callback param, it falls back to plain JSON like res.json().

  • When to choose it:

    • Only for old browsers/clients that predate CORS and must fetch cross-domain data.

    • Otherwise prefer res.json() plus proper CORS headers: JSONP has security downsides and can't do non-GET requests.

Q44.
How does Express identify a middleware function as an error-handling middleware?

Mid

Express recognizes error-handling middleware purely by its arity: a function declared with four arguments (err, req, res, next) is treated as an error handler and only invoked when an error is passed to next(err).

  • Four parameters is the signal:

    • Express inspects fn.length; exactly 4 marks it as an error handler.

    • You must declare all four even if unused, and err must be first.

  • When it runs:

    • Only after an error enters the pipeline via next(err) (or, in Express 5, a rejected async handler).

    • Normal requests skip it; regular 3-arg middleware skips when an error is active.

  • Register it last, after all routes, so it can catch errors from everything above.

javascript

// 4 args => error handler app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: err.message }); });

Q45.
What makes error-handling middleware unique in Express? Why does it require four arguments (err, req, res, next) instead of three?

Mid

Error-handling middleware is identified by its arity: Express recognizes a function with exactly four parameters (err, req, res, next) as an error handler and calls it only when an error is passed down the chain.

  • Express inspects function length: A 3-arg function is normal middleware; a 4-arg function is treated as an error handler. The extra err as the first param is the signal.

  • It runs only on errors: Normal middleware is skipped once an error is in flight; Express jumps straight to the next error handler.

  • Triggered by next(err): Calling next() with any argument routes execution to error handlers, bypassing remaining regular middleware.

  • Gotcha: You must declare all four params even if next is unused, or Express won't recognize it as an error handler.

javascript

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

Q46.
How do you implement a centralized error handler in Express? Why is it considered a best practice compared to handling errors inside every individual route?

Mid

A centralized error handler is a single 4-arg error middleware registered last, to which every route forwards errors via next(err). It keeps error formatting, logging, and status codes in one place instead of scattered across routes.

  • How to implement it:

    1. In each route, pass errors down with next(err) (or throw in sync code).

    2. Register one app.use((err, req, res, next) => ...) after all routes.

    3. Map error types to status codes and a consistent response shape there.

  • Why it is best practice:

    • DRY: one place to log, format, and set status, no duplicated try/catch responses.

    • Consistency: every client gets the same error structure.

    • Separation of concerns: routes focus on business logic; the handler owns error policy.

  • Tip: Use a custom error class carrying status and message so the central handler can respond appropriately.

Q47.
How do you handle errors in synchronous vs. asynchronous code in Express 4?

Mid

In Express 4, synchronous errors thrown inside a handler are caught automatically and routed to the error handler, but asynchronous errors are not: you must forward them manually with next(err).

  • Synchronous code: A plain throw inside a route is caught by Express and sent to the error-handling middleware automatically.

  • Asynchronous code:

    • Errors in callbacks, promises, or async functions escape Express's try/catch, so you must call next(err) yourself.

    • With promises, use .catch(next); with async/await, wrap in try/catch and call next(err).

  • Helper pattern: A wrapper like express-async-handler (or a small asyncHandler) auto-forwards rejected promises to next.

javascript

// sync: auto-caught app.get('/sync', (req, res) => { throw new Error('boom'); }); // async: must forward app.get('/async', async (req, res, next) => { try { res.json(await getData()); } catch (err) { next(err); } });

Q48.
Why is it necessary to pass errors to next(err) in Express 4, especially inside asynchronous blocks?

Mid

In Express 4, next(err) is the only way asynchronous errors reach the error-handling middleware: Express's automatic try/catch only wraps the synchronous execution of the handler, so a rejection or callback error after an await is invisible to it unless you forward it.

  • The event loop breaks the call stack: By the time an async operation fails, the original handler call has already returned, so Express can't catch the error at that point.

  • next(err) re-enters the middleware chain: Passing any argument to next tells Express to skip normal middleware and invoke the error handler.

  • Without it: The request hangs (no response ever sent) or the unhandled rejection can crash the process.

  • Express 5 note: Express 5 auto-forwards rejected promises from async handlers, reducing the need for manual next(err).

Q49.
What is the "default error handler" in Express and what does it do if you don't define a custom one?

Mid

The default error handler is Express's built-in fallback: if an error reaches the end of the middleware chain and you haven't defined your own error handler, Express responds automatically with a sensible error page.

  • What it sends: Sets the status from err.status or err.statusCode (defaults to 500) and writes the error message.

  • Environment-aware: In development it includes the stack trace; when NODE_ENV is production, it hides the stack to avoid leaking internals.

  • Header safety: If headers were already sent, it delegates to Node's default handler and closes the connection.

  • Custom handlers override it: Defining a 4-arg error middleware replaces this behavior, but call next(err) to fall back to the default if you don't respond.

Q50.
What is express-async-errors and why might you use it in an Express 4 project?

Mid

express-async-errors is a small patch that lets errors thrown in async route handlers automatically reach Express's error-handling middleware. In Express 4, a rejected promise inside an async handler is not caught by Express, so without it you must manually wrap every handler.

  • The problem it solves: Express 4 does not await handler return values, so a thrown/rejected error in async code becomes an unhandled rejection and the request hangs.

  • How it works: Just require('express-async-errors') once at startup; it monkey-patches the router so rejected promises are routed to next(err) automatically.

  • Why use it: Removes the boilerplate of wrapping every handler with a catch(next) helper.

  • Alternatives: A manual asyncHandler wrapper, or upgrading to Express 5, which natively forwards rejected promises to error handlers.

javascript

require('express-async-errors'); app.get('/user/:id', async (req, res) => { const user = await db.find(req.params.id); // if this rejects... res.json(user); // ...error goes to app.use((err,...)) });

Q51.
Explain the difference between res.locals and app.locals. Which one would you use to pass data to a view template for a single request versus the entire application lifetime?

Mid

res.locals holds data scoped to the current request/response cycle, while app.locals holds data that lives for the entire application lifetime. Use res.locals for per-request view data and app.locals for app-wide constants.

  • res.locals (per request):

    • Reset on every request; automatically exposed to views rendered by that response.

    • Ideal for request-specific data: the logged-in user, flash messages, CSRF tokens.

    • Commonly populated in middleware, e.g. res.locals.user = req.user.

  • app.locals (whole app lifetime):

    • Set once and shared across all requests until the process restarts.

    • Ideal for constants: site name, app version, helper functions available in every template.

  • Both are merged into the template context: When you call res.render(), Express combines app.locals, res.locals, and the render params.

javascript

// App-wide: set once app.locals.siteName = 'My App'; // Per-request: set in middleware app.use((req, res, next) => { res.locals.currentUser = req.user; next(); });

Q52.
Explain the difference between app.set() and app.enable().

Mid

app.enable(name) is just a convenience shorthand for app.set(name, true) for boolean settings, while app.set() can assign any type of value. They operate on the same underlying settings store.

  • app.set(name, value): General-purpose: value can be a string, number, object, or boolean.

  • app.enable(name) / app.disable(name): Boolean-only helpers equal to app.set(name, true) and app.set(name, false).

  • Companion checks: app.enabled(name) and app.disabled(name) return the boolean status of a setting.

javascript

app.enable('trust proxy'); // same as: app.set('trust proxy', true); app.enabled('trust proxy'); // true

Q53.
What is the role of the helmet middleware in an Express application?

Mid

helmet is a middleware that hardens an Express app by setting a collection of HTTP security headers with sensible defaults, reducing common web vulnerabilities.

  • Sets protective response headers: e.g. Content-Security-Policy, X-Content-Type-Options, Strict-Transport-Security, X-Frame-Options.

  • Mitigates known attack classes: Reduces XSS, clickjacking, MIME-sniffing, and protocol-downgrade risks.

  • Collection of small middlewares: Each header is a toggleable sub-middleware, so you can disable or customize any (e.g. tune contentSecurityPolicy).

  • Applied early: Mount it near the top with app.use(helmet()) so headers apply to all responses.

javascript

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

Q54.
How do you handle rate limiting in Express to prevent brute force or DoS attacks?

Mid

You throttle requests per client using a rate-limiting middleware like express-rate-limit, which counts requests in a time window and rejects clients that exceed a threshold with HTTP 429.

  • Window-based counting: Define a windowMs and max requests per key (usually IP); over the limit returns 429 Too Many Requests.

  • Target sensitive routes: Apply stricter limits on login/auth endpoints to blunt brute-force attempts.

  • Shared store for scale: In-memory counters break across multiple instances; use a Redis store (rate-limit-redis) so the limit is global.

  • Trust the real client IP: Behind a proxy set app.set('trust proxy', ...) so req.ip reflects X-Forwarded-For, not the proxy.

  • Defense in depth: Combine with account lockouts, CAPTCHAs, and edge/WAF limits for real DoS resilience.

javascript

const rateLimit = require('express-rate-limit'); const loginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 min max: 5, message: 'Too many attempts, try later', }); app.use('/login', loginLimiter);

Q55.
How do you handle Cross-Origin Resource Sharing (CORS) in Express?

Mid

CORS controls which cross-origin browsers may call your API; in Express you enable it with the cors middleware, which sets the appropriate Access-Control-* response headers.

  • It is a browser-enforced policy: The server just declares who is allowed; the browser blocks disallowed cross-origin responses. Non-browser clients ignore CORS.

  • Restrict origins explicitly: Pass an origin allowlist rather than *, especially when credentials are involved.

  • Credentials need explicit opt-in: Set credentials: true to allow cookies; you cannot combine credentials with a wildcard origin.

  • Preflight handling: The middleware answers OPTIONS preflight requests and advertises allowed methods/headers.

javascript

const cors = require('cors'); app.use(cors({ origin: ['https://app.example.com'], credentials: true, }));

Q56.
How does the CORS middleware work conceptually within the Express pipeline?

Mid

Conceptually the CORS middleware is a request interceptor: it inspects the Origin header, decides if the origin is allowed, attaches the matching Access-Control-* headers, and short-circuits preflight requests before they reach your route handlers.

  • Runs early in the pipeline: Mounted with app.use(cors()) it processes every incoming request before route logic.

  • Two request types:

    • Simple requests: it adds Access-Control-Allow-Origin and calls next().

    • Preflight OPTIONS: it responds immediately with allowed methods/headers and does not call downstream handlers.

  • Dynamic decisions: The origin option can be a function, letting you allow/deny per request at runtime.

  • It only sets headers: Enforcement happens in the browser; the middleware never blocks the actual server processing itself.

Q57.
How would you handle large file uploads in Express, and why is multer preferred over standard body-parsers for this?

Mid

Large uploads arrive as multipart/form-data, which JSON/urlencoded body-parsers can't handle; multer is purpose-built to stream and parse this format efficiently, writing files to disk (or a buffer) instead of holding everything in memory.

  • Body-parsers are wrong for files: express.json() / express.urlencoded() don't decode multipart binary data and would buffer huge payloads in memory.

  • multer streams multipart data: It parses file parts and text fields, exposing files on req.file/req.files and fields on req.body.

  • Storage engines: diskStorage writes to disk (best for large files); memoryStorage keeps a Buffer (only for small files).

  • Enforce safety limits: Set limits (max file size/count) and a fileFilter to reject bad MIME types.

  • Very large files: For huge uploads, stream directly to object storage (e.g. S3) rather than local disk.

javascript

const multer = require('multer'); const upload = multer({ dest: 'uploads/', limits: { fileSize: 10 * 1024 * 1024 }, // 10MB }); app.post('/upload', upload.single('file'), (req, res) => { res.json({ saved: req.file.filename }); });

Q58.
When would you use express.static() and what are the security implications of its configuration?

Mid

You use express.static() to serve static assets (HTML, CSS, JS, images) directly from a directory; its security risk is exposing more of the filesystem than intended, so you must scope the served directory carefully.

  • When to use it: Serving a built frontend or public assets without writing a route per file.

  • Serve a dedicated public folder: Point it at a folder that contains only public files, never your project root or source directory.

  • Watch out for dotfiles: Files like .env can leak; use the dotfiles: 'ignore' option and keep secrets out of the served path.

  • Path traversal is handled but stay strict: Express normalizes paths to block ../ escapes, but a misconfigured root still over-exposes files.

  • Caching headers: Use maxAge/etag options to control caching of assets.

javascript

app.use('/static', express.static('public', { dotfiles: 'ignore', maxAge: '1d', }));

Q59.
What are the tradeoffs of using express.json() vs. third-party body parsers?

Mid

express.json() is the built-in body parser (a rebadged body-parser) that covers the common JSON case; third-party parsers matter only when you need behavior it doesn't offer, like streaming, multipart, or higher performance.

  • express.json() strengths:

    • Zero extra dependency, maintained with Express, handles JSON with limit, strict, and content-type options.

    • Buffers the whole body into memory then parses, which is simple and safe for typical API payloads.

  • Where third-party parsers win:

    • multipart/form-data (file uploads) is not covered: you need multer or busboy.

    • Streaming/large payloads: a streaming parser avoids buffering gigabytes in RAM.

    • Speed: parsers like fast-json-body or custom logic can outperform on hot paths.

  • Tradeoff summary: use express.json() by default; reach for a third-party parser only for content types or performance/streaming needs it can't meet.

Q60.
What is the difference between express.raw() and express.text() body parsers, and when would you use them?

Mid

Both parse the raw request body but leave it unparsed as a structure: express.raw() gives you a Buffer, and express.text() gives you a plain string. You use them when you need the body exactly as sent, not decoded into JSON or key/value pairs.

  • express.raw() produces a Buffer: Use for binary payloads or when you must verify the exact bytes, e.g. validating a webhook signature (Stripe/GitHub) that hashes the raw body.

  • express.text() produces a string: Use for plain-text bodies like text/plain, XML, or CSV you parse yourself.

  • Both let you scope by content type via the type option, so they only fire on matching requests.

  • Rule of thumb: JSON/form use their dedicated parsers; use raw()/text() when byte-fidelity or custom parsing matters.

Q61.
What does the 'extended' option in express.urlencoded() control?

Mid

The extended option in express.urlencoded() controls which library parses the URL-encoded body and therefore whether nested objects and arrays are supported.

  • extended: false:

    • Uses the built-in querystring module; values are only strings or arrays of strings, no nesting.

    • a[b]=c would not become a nested object.

  • extended: true:

    • Uses the qs library, which supports rich nested objects and arrays.

    • a[b]=c parses to { a: { b: 'c' } }.

  • Practical note: true is more flexible; false is simpler and slightly safer/faster. There's no default, so you should set it explicitly.

Q62.
What is the purpose of express.json() and express.urlencoded()? Why were these moved from the body-parser library into the Express core?

Mid

express.json() and express.urlencoded() are middleware that read the incoming request body and populate req.body: JSON payloads and HTML-form (URL-encoded) payloads respectively. They were folded back into Express core from body-parser because they're near-universal needs and Express wanted them available without an extra install.

  • What each does:

    • express.json() parses application/json bodies into a JS object.

    • express.urlencoded() parses application/x-www-form-urlencoded form submissions.

    • Without them req.body is undefined.

  • Why moved into core:

    • They wrap the same body-parser code, so behavior is identical, just exposed on express.

    • Reduces dependency friction: the most common parsers ship with the framework (re-added in Express 4.16).

    • Note: multipart and other niche parsers stayed external.

javascript

app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.post('/user', (req, res) => { res.json(req.body); // populated by the parsers above });

Q63.
Explain how you would structure an Express project using the MVC pattern.

Mid

MVC splits an Express app into Models (data/business rules), Views (output rendering), and Controllers (request handling), with routes wiring URLs to controllers. The goal is separation of concerns: thin route files, logic in controllers/services, and persistence in models.

  • Layers:

    1. Models: schema and data access (e.g. Mongoose/Sequelize models) plus core domain rules.

    2. Views: templates (EJS, Pug) for server-rendered HTML; often omitted for pure JSON APIs.

    3. Controllers: functions that take req/res, call models/services, and send a response.

    4. Routes: map HTTP verbs and paths to controller functions via express.Router().

  • Typical folder layout: /models, /controllers, /routes, /views, plus /middleware and an entry app.js.

  • Good practice: add a service layer between controllers and models so controllers stay thin and business logic is reusable and testable.

javascript

// routes/users.js const router = require('express').Router(); const ctrl = require('../controllers/userController'); router.get('/:id', ctrl.getUser); module.exports = router; // controllers/userController.js const User = require('../models/User'); exports.getUser = async (req, res) => { const user = await User.findById(req.params.id); res.json(user); };

Q64.
Explain the concept of mounting an Express app inside another Express app. When is this useful for large-scale modularity?

Mid

Mounting means attaching a sub-application or router at a base path with app.use('/path', subApp): the sub-app handles everything under that prefix as its own self-contained mini Express app. It's a key tool for modularity because each feature can be developed, configured, and reasoned about in isolation.

  • How it works:

    • A mounted app/router has its own middleware stack, routes, and even settings.

    • The mount path is stripped, so inside the sub-app routes are relative (req.baseUrl holds the prefix).

    • express.Router() is the lightweight, common form; a full express() instance can be mounted too.

  • When it helps at scale:

    • Domain modules: mount /users, /orders, /admin as independent routers owned by different teams.

    • API versioning: mount separate apps at /api/v1 and /api/v2.

    • Per-module middleware: apply auth or rate limits to a whole mounted subtree in one place.

javascript

// users.js const router = require('express').Router(); router.get('/', listUsers); // handles GET /users module.exports = router; // app.js app.use('/users', require('./users')); app.use('/api/v2', require('./v2'));

Q65.
How do you handle input validation in an Express app, and where in the pipeline should validation middleware sit?

Mid

Validate incoming data with a schema/validation library (express-validator, Joi, zod) in middleware that runs before the route handler, so handlers only ever see clean, well-formed input.

  • Validate early in the pipeline: Validation middleware should sit after body parsers (express.json()) but before controllers, so bad input is rejected before any business logic runs.

  • Validate all untrusted sources: Check req.body, req.params, req.query, and headers as needed, not just the body.

  • Fail with a clear 400: On failure return 400 Bad Request with structured error details; centralize this in an error handler so responses stay consistent.

  • Prefer schema-driven validation: A schema also sanitizes/coerces (trim, cast types) and keeps rules declarative and reusable across routes.

javascript

const { body, validationResult } = require('express-validator'); app.post('/users', body('email').isEmail(), body('age').isInt({ min: 0 }), (req, res, next) => { const errors = validationResult(req); if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() }); next(); }, createUser );

Q66.
What options can you pass to res.cookie(), and how do the httpOnly, secure, and sameSite flags improve cookie security?

Mid

res.cookie() accepts an options object controlling lifetime, scope, and security. The security flags httpOnly, secure, and sameSite each defend against a different attack class.

  • Common options:

    • maxAge/expires: lifetime (omit both for a session cookie).

    • path and domain: which URLs the cookie is sent to.

    • signed: sign the value (requires a secret via cookie-parser) to detect tampering.

  • httpOnly: Hides the cookie from JavaScript (document.cookie), mitigating theft via XSS.

  • secure: Cookie is only sent over HTTPS, preventing interception on plaintext connections.

  • sameSite: Controls cross-site sending: 'strict' or 'lax' reduce CSRF; 'none' allows cross-site but requires secure.

javascript

res.cookie('session', id, { httpOnly: true, secure: true, sameSite: 'lax', maxAge: 24 * 60 * 60 * 1000 });

Q67.
How do sessions work in Express with express-session, and what is the difference between session-based (stateful) and cookie-only (stateless) approaches?

Mid

express-session stores session data on the server and gives the client only a signed session ID cookie; on each request it looks up that ID to restore req.session. This is stateful, versus a stateless approach that keeps all data (e.g. a JWT) in the cookie itself.

  • How express-session works:

    • On first request it creates a session, stores data in a store, and sets a cookie with the session ID.

    • Later requests send the ID cookie; the middleware loads the data into req.session.

  • Session-based (stateful):

    • Server holds the truth, so sessions can be revoked instantly and the cookie stays small.

    • Needs shared storage to scale across multiple servers.

  • Cookie-only (stateless):

    • All claims live in the (signed) token, so no server lookup and easy horizontal scaling.

    • Harder to revoke before expiry and the payload travels on every request.

javascript

app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: true } })); app.get('/', (req, res) => { req.session.views = (req.session.views || 0) + 1; res.send(`views: ${req.session.views}`); });

Q68.
What is content negotiation in Express, and how do req.accepts() and res.format() help you serve different response types based on the client's Accept header?

Mid

Content negotiation is choosing what representation to send based on what the client says it can accept, primarily via the Accept request header. Express gives you req.accepts() to inspect that header and res.format() to branch response logic per media type.

  • req.accepts():

    • Takes one or more types and returns the best match against the client's Accept header, or false if none acceptable.

    • Respects quality values (q) and ordering, so it picks what the client actually prefers.

    • Siblings exist for other headers: req.acceptsCharsets(), req.acceptsEncodings(), req.acceptsLanguages().

  • res.format():

    • Takes an object keyed by MIME type or extension; Express runs the callback for the best match and sets Content-Type automatically.

    • Provide a default handler; otherwise a non-match responds 406 Not Acceptable.

  • Use them together: res.format() is the declarative shortcut, req.accepts() gives finer manual control.

javascript

app.get('/data', (req, res) => { res.format({ 'text/plain': () => res.send('hello'), 'application/json': () => res.json({ msg: 'hello' }), default: () => res.status(406).send('Not Acceptable'), }); });

Q69.
How does req.ip work, and how does the 'trust proxy' setting affect the value it returns?

Mid

req.ip returns the client's IP address. By default it's the IP of the immediate socket connection, but when your app sits behind a proxy or load balancer, the trust proxy setting tells Express to instead derive the client IP from the X-Forwarded-For header.

  • Default behavior: With trust proxy disabled, req.ip is the connecting peer, which behind a proxy is the proxy's IP, not the real client.

  • Enabling trust proxy:

    • Set via app.set('trust proxy', ...); Express then walks X-Forwarded-For to find the leftmost untrusted address.

    • Accepts several value types: true, a number of hops, an IP/subnet list, or a custom function.

  • Security note: Only trust the proxy when you actually control it; X-Forwarded-For is client-spoofable otherwise.

javascript

app.set('trust proxy', 1); // trust first proxy (e.g. nginx) app.get('/', (req, res) => res.send(req.ip));

Q70.
What are the primary differences between Express 4 and Express 5 that a developer should be aware of?

Mid

Express 5 is a modernization release: it drops ancient Node support, upgrades path-to-regexp (changing route syntax), and simplifies async error handling, while keeping the overall API largely familiar.

  • Async error handling: Rejected promises returned from middleware/handlers are now forwarded to the error handler automatically, reducing manual try/catch.

  • Route path syntax: New path-to-regexp version changes wildcards and optional segments (e.g. * must be named, ? optional syntax changed).

  • Removed/renamed methods: app.del() gone (use app.delete()), res.sendfile() removed, and several deprecated APIs cleaned up.

  • Dropped legacy support: Requires modern Node.js versions; drops very old runtimes.

  • Behavioral tweaks: req.query parsing default changed and some methods now throw clearer errors on bad input.

Q71.
How has the app.del() method changed in newer versions of Express?

Mid

app.del() was an old alias for registering DELETE routes, created because delete was a reserved word in older JavaScript. It was deprecated in Express 4 and fully removed in Express 5; you now use app.delete().

  • Why it existed: Early JS engines couldn't reliably use delete as a method name, so del was the workaround.

  • Current status:

    • Modern JS allows reserved words as property names, so the alias is obsolete.

    • Calling app.del() in Express 5 throws; migrate to app.delete().

javascript

// Old (removed): app.del('/user/:id', handler); // New: app.delete('/user/:id', handler);

Q72.
Which methods were deprecated or renamed in the transition from Express 4 to 5?

Mid
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q73.
How does res.render() work with a view engine like EJS or Pug at the Express level?

Mid
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q74.
What is the difference between res.sendFile() and res.download()? How does Express handle the Content-Disposition header in these cases?

Mid
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q75.
What does the compression middleware do, and what are the tradeoffs of enabling response compression in Express?

Mid
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q76.
How do you test Express routes and middleware using supertest, and why is it preferred over spinning up a live server?

Mid
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q77.
Conceptually, how does Express's unopinionated philosophy differ from a framework like NestJS? What are the trade-offs of having no built-in project structure?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q78.
Compare Express to Koa or Fastify. What are the primary architectural tradeoffs?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q79.
Why should you set NODE_ENV to production, and what other production best practices (process manager, reverse proxy) apply to an Express app?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q80.
In Express 4, why do thrown errors in async route handlers cause the process to hang or crash? How does Express 5 change the way rejected promises are handled natively?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q81.
How do you implement a centralized error-logging system within an Express app?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q82.
Why do thrown errors in async route handlers crash an Express 4 server?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q83.
What is the difference between a router-level error handler and an application-level error handler, and how does error propagation work across mounted routers?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q84.
What does app.set('trust proxy', true) do? Why is this setting critical when running an Express app behind a reverse proxy like Nginx or a Load Balancer?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q85.
How would you protect an Express application against CSRF attacks?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q86.
What are the key security best practices you would apply when deploying an Express app to production?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q87.
Explain how express.static serves files and why you might use a reverse proxy like Nginx in front of it in production.

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q88.
How does express.static work under the hood? If you have a file named index.html in your static folder and a route defined as app.get('/'), which one takes precedence?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q89.
How would you structure an Express app to serve a single-page application while also exposing a JSON API?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q90.
How would you organize controllers, services, and middleware to keep route files thin in a large Express codebase?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q91.
Why is the default MemoryStore in express-session not suitable for production, and what would you use instead?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q92.
How has route matching changed in Express 5 (path-to-regexp)?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q93.
Beyond async error handling, what are some of the major changes in Express 5 regarding route matching syntax (path-to-regexp) and deprecated methods like res.sendfile?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q94.
How does Express handle ETags and caching, and how can they improve performance of your responses?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q95.
How can you stream a large file or response inside an Express route handler using pipes?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.