Overview
Express is the most widely used web framework for Node.js, and interviewers use it to test whether you understand middleware composition, routing, and how the framework builds on top of Node's raw http module. This guide covers the questions that recur most often across Express interviews, with precise answers grounded in how Express actually works internally.
Cricket analogy: Just as a bowling coach probes whether a fast bowler truly understands seam position and not just raw pace, Express interviews probe whether you grasp middleware and routing, not just that you've used app.get().
Frequently Asked Questions
Q: What is middleware in Express, and why does order matter?
Middleware are functions with the signature (req, res, next) that execute sequentially in the order they are registered via app.use() or route methods, each able to modify req/res, end the request-response cycle, or pass control forward by calling next(). Order matters because Express processes middleware as a pipeline: a middleware that isn't reached (because an earlier one didn't call next()) never runs, and middleware registered after a route handler that sends a response will not execute for that request.
Cricket analogy: Middleware run in fielding-position order: if the wicketkeeper (first middleware) doesn't relay the ball onward (next()), the slip fielders positioned after never get a chance to react to that ball at all.
Q: What is the signature of an error-handling middleware and how does Express recognize it?
Error-handling middleware has exactly four parameters: (err, req, res, next). Express identifies it as an error handler purely by this arity — even if you don't use all four parameters, you must declare all four for Express to treat the function differently from regular middleware. It is invoked when next(err) is called anywhere upstream, or when a synchronous error is thrown inside a route handler.
Cricket analogy: Error-handling middleware is identified purely by having four parameters, much like a review referee is identified purely by role, not by how many decisions they've actually reviewed that match.
Q: What is the difference between route parameters and query strings?
Route parameters are named segments defined in the route path (e.g., /users/:id) and are accessed via req.params; they are part of the URL path and typically identify a specific resource. Query strings are key-value pairs appended after a '?' in the URL (e.g., /users?sort=name) and are accessed via req.query; they're typically used for optional filtering, sorting, or pagination rather than identifying a resource.
Cricket analogy: Route params are like a scorecard entry naming which specific batsman is out (/batsman/:id), while query strings are like optional filters on a stats page (?season=2023&format=odi) refining what you see.
Q: How does Express differ from the raw Node.js http module?
The http module gives you a bare request/response API where you must manually parse URLs, handle routing with conditional logic, parse request bodies, and set headers yourself. Express is a thin layer built on top of http that adds a declarative routing system (app.get/post/etc.), a middleware pipeline, convenience methods on req/res (like res.json, res.status), and integration points for template engines and third-party middleware, all while still using an http.Server under the hood.
Cricket analogy: Raw http is like playing on an unmarked field where you must chalk your own boundary lines and rules each match; Express is like playing on a standard stadium with lines, umpires, and rules already provided.
Q: How do you serve static files in Express?
Express provides the built-in express.static(root) middleware, which serves files (HTML, CSS, JS, images) directly from a specified directory. For example, app.use(express.static('public')) serves files in the 'public' folder at the root URL path; you can also mount it under a prefix, e.g., app.use('/assets', express.static('public')).
Cricket analogy: express.static is like a stadium's souvenir kiosk that just hands out pre-made merchandise from a stockroom (the 'public' folder) without any custom processing per request.
Q: What is the difference between app.use() and app.get()/app.post()?
app.use() mounts middleware for all HTTP methods on a given path prefix (matching the path and anything beneath it unless it's an exact match middleware), making it suitable for cross-cutting concerns like logging, body parsing, or auth. app.get()/app.post()/etc. register route handlers tied to a specific HTTP method and an exact (or pattern-matched) path, used for defining actual endpoint logic.
Cricket analogy: app.use() is like a ground rule that applies to the whole innings regardless of who's batting, while app.get()/app.post() are like specific instructions for exactly one named delivery scenario.
Q: How does Express handle asynchronous errors in route handlers?
In Express 4, errors thrown inside synchronous route handlers are caught automatically, but errors thrown inside async functions or rejected promises are NOT automatically caught — you must call next(err) explicitly in a .catch(), or wrap handlers in a helper that forwards rejections to next(). Express 5 changes this by automatically catching rejected promises returned from async handlers and forwarding them to the error-handling middleware.
Cricket analogy: In older rules, a runout during normal play (sync error) is caught by the umpire automatically, but a dispute during a DRS review (async rejection) needed the third umpire to be explicitly called in Express 4, while Express 5 automatically escalates it.
Q: What is the purpose of express.Router()?
express.Router() creates a modular, mountable set of route handlers that behaves like a mini Express application. It lets you group related routes (e.g., all /users routes) into a separate file, apply middleware scoped only to that group, and then mount the whole router onto the main app with app.use('/users', userRouter), keeping route definitions organized and maintainable.
Cricket analogy: express.Router() is like a franchise's junior academy that runs its own drills and rules internally, then gets folded into the main national team setup via a single mounting agreement.
Q: How do you handle 404 (Not Found) responses in Express?
Because Express doesn't send a 404 automatically for unmatched routes beyond a default fallback, best practice is to add a catch-all middleware after all defined routes (and before the error handler) that creates a 404 response — since Express processes middleware/routes top-to-bottom, any request that didn't match an earlier route falls through to this handler.
Cricket analogy: Since there's no automatic 'no result' call, umpires add a final catch-all ruling after checking all specific dismissal appeals, so any unclaimed situation still gets a definitive decision before the match report is filed.
Quick Reference
- Middleware signature: (req, res, next); error middleware signature: (err, req, res, next) — exactly four params.
- Middleware execute in registration order; next() passes control to the next matching handler.
- req.params reads route path segments (e.g., :id); req.query reads the '?key=value' query string.
- express.static(dir) serves static assets directly from a folder.
- Express wraps Node's http module, adding routing, middleware, and req/res helper methods.
- app.use() applies to all HTTP methods on a path prefix; app.get/post are method- and path-specific.
- Express 4 does not auto-catch async/promise errors in route handlers; you must call next(err) yourself.
- Express 5 auto-forwards rejected promises from async handlers to error middleware.
- express.Router() groups related routes into a mountable, modular mini-app.
- A catch-all middleware placed after all routes handles unmatched (404) requests.
Key Takeaways
- Middleware order and calling next() correctly are the foundation of how Express request handling works.
- Error-handling middleware is identified by its four-parameter signature, not by name or position alone.
- req.params identifies resources via the URL path; req.query carries optional filtering/sorting data.
- Express adds routing, middleware, and convenience methods on top of Node's raw http module.
- Async errors need explicit next(err) forwarding in Express 4, but are automatic in Express 5.
Practice what you learned
1. How many parameters must an error-handling middleware function declare for Express to recognize it as such?
2. Given the route path '/products/:id', how would you access the value of ':id' inside the handler?
3. Which built-in Express middleware serves static files from a directory?
4. In Express 4, what happens if an async route handler throws inside a try block that isn't caught, or a returned promise rejects without being handled?
5. What is the primary purpose of express.Router()?
Was this page helpful?
You May Also Like
Middleware in Express
Master the Express middleware chain, the next() function, and the special error-handling middleware signature.
Error Handling in Express
Master synchronous and asynchronous error handling in Express using 4-argument error middleware.
Common Node.js Interview Questions
A curated set of frequently asked Node.js interview questions with clear, technically accurate answers.
Common Node.js & Express Pitfalls
Real-world mistakes developers make with Node.js and Express, why they're harmful, and how to fix them.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics