Skip to main content

Command Palette

Search for a command to run...

What is Middleware in Express and How It Works

Published
6 min read
What is Middleware in Express and How It Works
S
I write code , that run in the browser and someone else's machine. And sometimes I also write articles

In Express.js, middleware is one of the most important concepts for building scalable, flexible web applications and APIs. Middleware lets you plug into the request/response cycle and run logic before requests reach your main route handlers or before responses are sent back to clients.

Think of middleware as checkpoints or assembly-line stations: every incoming request passes through one or more middleware functions before getting a response.

Let’s break down what middleware is, where it fits in Express, and see practical examples for common use cases.


What Is Middleware in Express?

A middleware in Express is simply a function that receives the request and response objects (just like a route handler), but can do three main things:

  1. Read or modify the request before it reaches the route handler.

  2. Read or modify the response before it goes back to the client.

  3. Decide whether the request should continue, pass control to the next middleware, or end the request/response cycle.

Basic Middleware Signature:

function myMiddleware(req, res, next) {
  // ...logic here
  next(); // Pass control to the next middleware or route
}

Notice the third argument: next. This is a special function provided by Express to move the request along the pipeline.


Where Middleware Sits in the Request Lifecycle

When a request hits your Express app:

  1. The request enters Express.

  2. It passes through any configured middleware functions in order.

  3. Eventually it reaches a route handler (if not ended early by middleware).

  4. The response is sent and the cycle ends.

Analogy:
Imagine a package traveling through an assembly line.
Each station (middleware) can check it, add a sticker, reject it, wrap it, or send it to the next station.
Finally, the package is delivered (response sent back).


Types of Middleware in Express

Express supports several types of middleware, each suited for different use cases.

1. Application-Level Middleware

These are functions applied to the whole app.

Example: Logging Middleware

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

app.use((req, res, next) => {
  console.log(`\({req.method} \){req.url}`);
  next();
});
  • app.use() applies the middleware to every request.

  • You must call next() to let the pipeline continue!

2. Router-Level Middleware

Middleware attached to specific routers or sets of routes.

Example: Protect Admin Routes

const express = require("express");
const adminRouter = express.Router();

adminRouter.use((req, res, next) => {
  if (!req.user || !req.user.isAdmin) {
    return res.status(403).send("Forbidden");
  }
  next();
});

adminRouter.get("/dashboard", (req, res) => {
  res.send("Admin Dashboard");
});

You attach the router to the app (app.use("/admin", adminRouter);) and only /admin routes will use that middleware.

3. Built-In Middleware

Express provides built-in middleware for common needs:

  • express.json() – Automatically parses incoming JSON requests.

  • express.urlencoded() – Parses URL-encoded form data.

  • express.static() – Serves static files like images or CSS.

Example:

app.use(express.json());

Now every incoming JSON body is parsed and accessible as req.body.


Execution Order of Middleware in Express

Order matters!
Express runs middleware in the order you define it.

app.use(middlewareA);
app.use(middlewareB);

app.get("/hello", routeHandler);
  • A request goes to middlewareA first, then middlewareB, then routeHandler.

  • If any middleware does not call next(), the request halts immediately and never reaches the route.

Middleware can:

  • Continue to the next function (next())

  • End the response (res.send())

  • Pass errors to the next error handler (next(err))


Role of the next() Function

  • next() is how you tell Express to “move on” to the next thing in the pipeline.

  • Without next(), the request will hang forever (unless you send a response).

  • You can call next(err) to signal an error and invoke error-handling middleware.


Middleware Execution Sequence: A Visual Example

Consider:

app.use((req, res, next) => {
  console.log("First middleware");
  next();
});

app.use((req, res, next) => {
  console.log("Second middleware");
  next();
});

app.get("/", (req, res) => {
  res.send("Done!");
});

Request to / will print:

First middleware
Second middleware

And then respond with Done!.

If you send a response inside middleware (e.g., res.send("403 Forbidden")), Express skips all the remaining middleware and routes.


Real-World Examples of Middleware

1. Logging All Requests

app.use((req, res, next) => {
  console.log(`\({req.method} \){req.url} at ${new Date()}`);
  next();
});

2. Authentication “Checkpoint”

function authenticate(req, res, next) {
  if (!req.user) {
    return res.status(401).send("Unauthorized");
  }
  next();
}
app.use("/dashboard", authenticate);

3. Request Validation

function validateUserInput(req, res, next) {
  if (!req.body.username || !req.body.password) {
    return res.status(400).json({ error: "Missing fields" });
  }
  next();
}
app.post("/signup", validateUserInput, (req, res) => {
  // Create user
});
  • If validation fails, middleware ends the cycle with a 400 response.

  • If it passes, the actual signup route runs.


Request Pipeline Analogy

Picture every request passing through a pipeline of functions:

  • Middleware 1: Add user info if logged in.

  • Middleware 2: Validate the input.

  • Middleware 3: Log the request.

  • Route Handler: Process the request and send the response.

Each middleware can check, modify, or even stop the request before it ultimately reaches the actual route handler.


Best Practices & Notes

  • Place global middleware (like logging, JSON parsing) as early as possible.

  • Use router-level middleware for features needed only on some route groups (like admin auth).

  • Always call next() unless you send a response or hit an error.

  • Order of middleware is critical—earlier middleware can affect later middleware and route handlers.

  • Middleware can also return errors or responses, which halts the pipeline.


Conclusion

Middleware in Express works as a series of checkpoints between an incoming request and the final response. It allows you to:

  • Add features and behavior to your app without changing route handlers

  • Reuse common processing logic (like authentication, logging, input validation)

  • Control the flow of requests and responses

By mastering middleware, you gain powerful control over every request in your Express application, making your code modular, testable, and maintainable.