# What is Middleware in Express and How It Works

Modern web applications do much more than simply receive a request and send back a response. Before a response reaches the user, applications often need to:

*   Log request details
    
*   Verify authentication
    
*   Validate incoming data
    
*   Parse JSON
    
*   Handle errors
    

In Express.js, all these tasks are handled using **middleware**.

Middleware is one of the most important concepts in Express. Once you understand how middleware works, Express becomes much easier to use and scale.

* * *

## What is Middleware in Express?

Middleware in Express is a function that runs **between the incoming request and the final response**.

You can think of middleware as a **checkpoint** in the request lifecycle.

When a client sends a request to the server:

1.  The request enters the Express application
    
2.  Middleware functions process the request step-by-step
    
3.  Eventually, a response is sent back
    

Middleware can:

*   Read request data
    
*   Modify request or response objects
    
*   Execute logic
    
*   End the request-response cycle
    
*   Pass control to the next middleware
    

* * *

## Understanding Middleware with a Pipeline Analogy

Imagine an airport security process.

Before passengers board a flight, they go through several checkpoints:

1.  Identity check
    
2.  Security scan
    
3.  Ticket verification
    
4.  Boarding gate
    

Similarly, in Express:

1.  Request enters the server
    
2.  Middleware checks or processes the request
    
3.  Request moves through multiple middleware layers
    
4.  Final route handler sends the response
    

This sequence forms the **request pipeline**.

* * *

## Where Middleware Sits in the Request Lifecycle

Here is a simplified request flow:

```text
Client Request
      ↓
Middleware 1
      ↓
Middleware 2
      ↓
Middleware 3
      ↓
Route Handler
      ↓
Server Response
```

Each middleware gets access to:

```js
(req, res, next)
```

*   `req` → Incoming request data
    
*   `res` → Response object
    
*   `next` → Function that passes control to the next middleware
    

![](https://cdn.hashnode.com/uploads/covers/695a275cee3d7756437f49db/80994474-2d6a-4334-baf9-480d1d097a30.png align="center")

* * *

## Basic Middleware Example

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

const app = express();

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

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

app.listen(3000);
```

### What Happens Here?

1.  User visits `/`
    
2.  Middleware runs first
    
3.  Message prints in console
    
4.  `next()` moves request forward
    
5.  Route handler sends response
    

Without `next()`, the request would stop there.

* * *

## The Role of `next()` Function

The `next()` function is extremely important in Express middleware.

It tells Express:

> "This middleware is done. Move to the next step."

Example:

```js
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("Final response");
});
```

### Execution Order

```text
First middleware
Second middleware
Final response
```

* * *

## What Happens If `next()` Is Not Called?

If middleware neither:

*   sends a response
    
*   nor calls `next()`
    

the request gets stuck.

Example:

```js
app.use((req, res, next) => {
    console.log("Request received");
});
```

This middleware blocks the request pipeline because execution never moves forward.

* * *

## Types of Middleware in Express

Express provides multiple types of middleware.

* * *

## 1\. Application-Level Middleware

Application-level middleware is attached directly to the Express app using:

```js
app.use()
```

or specific HTTP methods.

Example:

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

This middleware runs for every request unless restricted.

* * *

### Middleware for Specific Routes

```js
app.use("/admin", (req, res, next) => {
    console.log("Admin middleware");
    next();
});
```

Now middleware only runs for routes starting with `/admin`.

* * *

## 2\. Router-Level Middleware

Express routers allow grouping related routes together.

Middleware can also be attached to routers.

Example:

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

const router = express.Router();

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

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

module.exports = router;
```

Router middleware only affects routes inside that router.

This helps organize large applications cleanly.

* * *

## 3\. Built-in Middleware

Express includes some built-in middleware functions.

### JSON Middleware

```js
app.use(express.json());
```

This parses incoming JSON request bodies.

Without it:

```js
req.body
```

would be undefined for JSON requests.

* * *

### Static File Middleware

```js
app.use(express.static("public"));
```

This serves static files like:

*   HTML
    
*   CSS
    
*   JavaScript
    
*   Images
    

from the `public` folder.

* * *

## Understanding Middleware Execution Order

Middleware runs **in the order it is defined**.

This is one of the most important rules in Express.

Example:

```js
app.use((req, res, next) => {
    console.log("Middleware A");
    next();
});

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

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

Execution:

```text
Middleware A
Middleware B
Route Handler
```

* * *

## Why Execution Order Matters

Suppose authentication middleware is placed after protected routes.

```js
app.get("/profile", (req, res) => {
    res.send("Profile Page");
});

app.use(authMiddleware);
```

This is incorrect because the route executes before authentication.

Correct approach:

```js
app.use(authMiddleware);

app.get("/profile", (req, res) => {
    res.send("Profile Page");
});
```

Order directly affects application behavior.

* * *

## Real-World Middleware Examples

Middleware becomes powerful in real applications.

* * *

### 1\. Logging Middleware

Logging helps monitor incoming requests.

Example:

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

Output:

```text
GET /users
POST /login
```

This is useful for:

*   debugging
    
*   monitoring traffic
    
*   tracking API usage
    

* * *

### 2\. Authentication Middleware

Authentication middleware checks whether users are allowed to access protected routes.

Example:

```js
const authMiddleware = (req, res, next) => {
    const isLoggedIn = true;

    if (!isLoggedIn) {
        return res.status(401).send("Unauthorized");
    }

    next();
};

app.use(authMiddleware);
```

If authentication fails, middleware sends a response immediately.

Otherwise, request continues.

* * *

### 3\. Request Validation Middleware

Validation middleware checks incoming data before processing it.

Example:

```js
const validateUser = (req, res, next) => {
    const { name } = req.body;

    if (!name) {
        return res.status(400).send("Name is required");
    }

    next();
};

app.post("/users", validateUser, (req, res) => {
    res.send("User created");
});
```

This prevents invalid data from reaching business logic.

* * *

## Chaining Multiple Middleware Functions

Express allows multiple middleware functions in sequence.

Example:

```js
app.get(
    "/dashboard",
    authMiddleware,
    logMiddleware,
    (req, res) => {
        res.send("Dashboard");
    }
);
```

Execution flow:

```text
Authentication Check
        ↓
Logging Middleware
        ↓
Route Handler
```

This modular structure keeps code organized and reusable.

![](https://cdn.hashnode.com/uploads/covers/695a275cee3d7756437f49db/690eec9f-3487-4daf-aa4e-34dac0689c87.png align="center")

* * *

## Why Middleware is Important

Middleware is the backbone of Express applications.

It helps developers:

*   Separate concerns
    
*   Reuse logic
    
*   Keep routes clean
    
*   Improve maintainability
    
*   Build scalable applications
    

Without middleware, route handlers would become cluttered with repeated logic.

* * *

## Common Beginner Mistakes

## Forgetting `next()`

This causes requests to hang indefinitely.

* * *

### Wrong Middleware Order

Middleware placement changes application behavior.

Always define important middleware early.

* * *

### Putting Too Much Logic in One Middleware

Keep middleware focused on one responsibility.

Good examples:

*   authentication
    
*   validation
    
*   logging
    
*   parsing
    

* * *

## Final Thoughts

Middleware is what makes Express flexible and powerful.

Instead of writing all logic inside route handlers, Express lets developers create a request-processing pipeline where each middleware performs a specific task.

The key ideas to remember are:

*   Middleware sits between request and response
    
*   Middleware executes in sequence
    
*   `next()` moves execution forward
    
*   Order of middleware matters
    
*   Middleware keeps applications modular and maintainable
