Skip to main content

Command Palette

Search for a command to run...

What is Middleware in Express and How It Works

Updated
5 min read

If you are learning Express.js, there is one word you are going to hear constantly: Middleware.

At first, it sounds like some complex, intimidating computer science concept. But the truth is, middleware is just a function. It is the secret sauce that makes Express so powerful, flexible, and easy to use.

Let's break down exactly what middleware is, how the next() function works, and look at some real-world examples you will actually use in your projects.

1. What is Middleware? (The Checkpoint Analogy)

To understand middleware, you need to understand the lifecycle of a web request.

When a user visits your website or hits your API, they send a Request (req). Your server does some work, and eventually sends back a Response (res).

Middleware sits right in the middle of that journey.

Think of your Express server as a secure office building.

  • The Request is a visitor walking through the front door.

  • The Response is the visitor reaching the boss's office.

  • Middleware are the security guards and receptionists along the way.

Before the visitor reaches the boss, they might have to sign the guestbook (Logging middleware), show their ID badge (Authentication middleware), and pass through a metal detector (Validation middleware).

If the visitor passes a checkpoint, the guard lets them move to the next step. If they fail (like having an invalid ID badge), the guard kicks them out and sends an error response immediately, without ever bothering the boss.

2. The Magic of the next() Function

A middleware function in Express always has access to three things:

  1. The req (request) object.

  2. The res (response) object.

  3. The next function.

Here is what a basic middleware function looks like:

const myMiddleware = (req, res, next) => {
    console.log("A visitor just entered the building!");
    
    // Pass the baton to the next middleware or route
    next(); 
};

The next() function is crucial. If you don't call next(), the request just stops. The visitor is stuck at the security desk forever, and the user's browser will just spin and eventually time out. Calling next() tells Express, "I'm done with my checks, move on to the next step in the pipeline."

3. Types of Middleware

Express organizes middleware into a few different categories depending on how you use it.

Built-in Middleware

Express comes with some middleware out of the box so you don't have to write it yourself. The most common one is express.json(), which parses incoming JSON data (like form submissions) so your server can read it.

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

// Built-in middleware
app.use(express.json());

Application-Level Middleware

This is middleware attached directly to your app object using app.use(). It runs for every single request that hits your server.

// This runs for every incoming request
app.use((req, res, next) => {
    console.log(`Time: ${Date.now()}`);
    next();
});

Router-Level Middleware

If your app is large, you probably use express.Router() to split your routes into different files. Router-level middleware works exactly like application-level, but it is bound to a specific router.

const router = express.Router();

// This only runs for routes handled by this specific router
router.use((req, res, next) => {
    console.log("Checking router-specific rules...");
    next();
});

4. Execution Order (Top to Bottom!)

The most important rule of middleware is that Express executes it in the exact order it is written in your code.

If you put a route before your built-in JSON middleware, that route won't be able to read JSON data. If you put an authentication check after the dashboard route, anyone can view the dashboard without logging in!

Always structure your app logically:

  1. Global Middleware (like express.json() and logging)

  2. Authentication Middleware

  3. Your Routes

  4. Error Handling Middleware (always goes at the very bottom)

5. Real-World Examples

Here is how you will actually use middleware in your day-to-day coding.

1. Logging (Who is visiting?)

Keep track of every request hitting your server for debugging purposes.

const logger = (req, res, next) => {
    console.log(`\({req.method} request made to: \){req.url}`);
    next();
};

app.use(logger);

2. Authentication (Are they allowed?)

Check if a user has a valid token before letting them see sensitive data.

const requireLogin = (req, res, next) => {
    const isLoggedin = true; // Imagine checking a real database or token here

    if (isLoggedin) {
        next(); // They are allowed, move on!
    } else {
        res.status(401).send("Access Denied. Please log in."); // Stop the request here
    }
};

// Protect a specific route
app.get('/dashboard', requireLogin, (req, res) => {
    res.send("Welcome to your secret dashboard!");
});

3. Request Validation (Is the data correct?)

Make sure the user sent the right information before trying to save it to a database.

const validateNewUser = (req, res, next) => {
    const { username, password } = req.body;

    if (!username || !password) {
        return res.status(400).send("Missing username or password!");
    }
    
    next(); // Data is good, proceed to create the user
};

app.post('/register', validateNewUser, (req, res) => {
    res.send("User registered successfully!");
});

Summary

Middleware in Express is simply a function that intercepts a request before it reaches its final destination. It can modify the request, log information, check permissions, or stop the request entirely.

Just remember the checkpoint analogy, always remember to call next(), and keep your code flowing from top to bottom. Happy coding!

More from this blog

Web Devlopment Journey

48 posts

In this publication, you will find articles related to web devlopment whether it be git or node.js. There will be blogs on every single topic and more will be coming soon...