Interview Q&A / Node.js

BeginnerIn-depth2 min readUpdated 2 Oct 2026

What is middleware in Express.js and how does next() work?

SHORT ANSWER

Middleware is a function that runs between the request arriving and the response being sent. It receives req, res and next, and it either ends the response or calls next() to pass control to the next middleware or route. Calling next(err) jumps to error-handling middleware.

Explain it simply

Think of entering an exam hall. First a guard checks your admit card. Then someone checks your ID. Then someone notes your entry time. Only then do you reach your seat. Each person can let you move on, or stop you right there ("no admit card, you cannot enter").

Express middleware works the same way. A request passes through a line of functions, in the order you registered them. Each one can read or change the request, send a response, or hand over to the next one by calling next(). The route handler at the end is just the last stop in the line.

Example

js
const express = require("express");
const app = express();

// 1. Runs for every request: logs method, URL and time taken.
app.use((req, res, next) => {
  const start = Date.now();
  res.on("finish", () => {
    console.log(`${req.method} ${req.url} ${Date.now() - start}ms`);
  });
  next();
});

// 2. Built-in middleware: parses JSON bodies into req.body.
app.use(express.json());

// 3. Custom auth check, used only on some routes.
function requireLogin(req, res, next) {
  if (!req.headers.authorization) {
    return res.status(401).json({ error: "Please log in" });
  }
  next();
}

app.get("/orders", requireLogin, (req, res) => {
  res.json([{ id: 1, item: "Masala dosa", price: 120 }]);
});

// 4. Error handler: has four arguments.
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: "Something went wrong" });
});

app.listen(3000);

How it works

  • app.use(fn) adds middleware for every path (or for a path prefix, like app.use("/api", fn)).
  • Middleware runs in the order it was added. Order matters: express.json() must come before routes that read req.body.
  • Each middleware must do one of two things: send a response, or call next(). If it does neither, the request hangs until it times out.
  • next(err) skips all normal middleware and goes to the first error handler, which Express recognises because it takes four arguments (err, req, res, next).
  • next("route") skips the remaining handlers for the current route.

Real-world use

Logging, parsing JSON or form bodies, CORS headers, authentication, rate limiting for an OTP endpoint, serving static files with express.static, and a central error handler that returns a clean message instead of a stack trace.

Common mistakes

  • Forgetting to call next(), so the request never finishes.
  • Calling next() after already sending a response, which leads to "Cannot set headers after they are sent".
  • Not using return before res.status(401).json(...), so code below still runs.
  • Registering the error handler before the routes. It must come last.

What to say in the interview

"Middleware in Express is a function with req, res and next that sits in the request pipeline. Middleware runs in the order it is registered. Each one can modify the request, end the response, or call next() to pass control on. I use it for logging, body parsing, authentication and rate limiting. Errors go through next(err) to an error-handling middleware with four parameters, which I register after all routes so the API returns a consistent error response."

Follow-up questions

  • How does Express know a middleware is an error handler?
  • What is the difference between app.use and app.get?
  • How do errors thrown inside async route handlers reach the error handler?

Go deeper

Read these once the basics above feel easy.

In Express 4, if an async route handler throws or its promise rejects, the error is not passed to next automatically, so people wrapped handlers or used a helper package. Express 5 handles this: a rejected promise from a handler or middleware is forwarded to next(err) for you. Router-level middleware (express.Router()) lets you group routes and attach middleware like requireLogin to a whole section such as /admin.

#nodejs#express#middleware#backend

Related questions

Practise more Node.js questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open Node.js quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.