How to Use Middleware Effectively in Express.js

BackerLeader posted 3 min read

Introduction

Not long ago, I was working on a project that required building an API in Express.js. Things were going smoothly until I realized I needed a way to log requests, handle authentication, and catch errors without cluttering every single route. That’s when middleware really clicked for me.

If you’re new to Express, middleware might feel like a mysterious black box. But trust me, once you understand it, you’ll see it’s the real backbone of any Express.js app. Let me walk you through how I approached it, and hopefully, you’ll avoid some of the early mistakes I made.


What is Middleware?

Think of middleware as a checkpoint for every request. Each request that hits your server passes through one or more middleware functions before it reaches the final destination (your route handler).

Here’s the simplest example I used when I was experimenting:

function myMiddleware(req, res, next) {
  console.log('Middleware running...');
  next(); // don’t forget this, or requests will hang forever
}

That next() function? It’s like telling Express: “I’m done here, pass it to the next handler.” If you forget it (and I definitely did a few times), you’ll stare at your browser forever waiting for a response.


Types of Middleware in Express

When I was first learning, I found it easier to break middleware into categories:

  1. Application-Level Middleware
    These run on every request unless you scope them to specific routes.

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

    I used this for quick logging in my first project, just to see what was going on.

  2. Router-Level Middleware
    Perfect when you want middleware only for a group of routes.

    const router = express.Router();
    
    router.use((req, res, next) => {
      console.log('Router middleware active');
      next();
    });
    
  3. Built-in Middleware
    Express saves you some time here with helpers like:

    • express.json() – parse JSON bodies
    • express.urlencoded() – parse form data
    app.use(express.json());
    app.use(express.urlencoded({ extended: true }));
    
  4. Third-Party Middleware
    This is where the community shines. For my project, I immediately installed morgan for logging and helmet for security.

    const morgan = require('morgan');
    app.use(morgan('dev'));
    
  5. Error-Handling Middleware
    This was a lifesaver. Instead of having try/catch everywhere, I just dropped this at the end:

    app.use((err, req, res, next) => {
      console.error(err.stack);
      res.status(500).send('Something broke!');
    });
    

Real-World Use Cases

Here are a few places middleware helped me in real projects:

  • Authentication – I had an internal dashboard that required a token check:

    function authMiddleware(req, res, next) {
      if (req.headers['authorization'] === 'secret-token') {
        next();
      } else {
        res.status(401).json({ error: 'Unauthorized' });
      }
    }
    
    app.use('/dashboard', authMiddleware);
    
  • Rate Limiting – Preventing abuse with express-rate-limit.

  • Logging Requests – Using morgan so I didn’t have to manually console.log.

  • Serving Static Files – With express.static(), I served uploaded images without writing extra code.


Best Practices I Learned

  1. Keep middleware modular – don’t dump everything in server.js.
  2. Always remember next() unless you’re sending a response.
  3. Place error-handling middleware at the end of your middleware stack.
  4. Don’t reinvent the wheel—use third-party middleware when possible.
  5. Think of middleware as a pipeline—each one should do a small, focused job.

✅ Conclusion

At first, middleware felt like “extra work,” but once I leaned on it properly, it made my code cleaner, easier to manage, and more professional.

So the next time you’re working on an Express project, don’t treat middleware as an afterthought—it’s what transforms a scrappy app into something maintainable and production-ready.


If you read this far, tweet to the author to show them you care. Tweet a Thanks

More Posts

How to set up TypeScript with Node.js and Express

Sunny - Jul 13

How to set up TypeScript with Node.js and Express (2025)

Sunny - Jun 6

Strengthening Web Security with HTTP Headers in Express.js

mariohhd - Aug 19

Node.js & Express.js: The Ultimate, Comprehensive, and Extremely Detailed Guide for Developers

Hanzla Baig Dev - Feb 27

Express and TypeScript: How to Set Up Your Project

Mubaraq Yusuf - May 26
chevron_left