What’s Express Middleware and Routing?
Think of Express as a pizza shop. Middleware are the chefs who prepare ingredients, add sauce, bake the pie, etc. Routing is the menu that tells the chefs what to make. Together they turn a list of code into a web‑app that users can visit.
Why Do You Need Middleware?
Middleware is a function that sits between the request coming in and the final route handler. It can read data, add data, or decide what to do next. Common uses:
- Parsing JSON bodies
- Logging requests
- Authenticating users
- Handling errors
- Serving static files
Because middleware runs in order, you can stack many of them to build a pipeline.
Getting Started: Build a Tiny Express App
const express = require('express');
const app = express();
const PORT = 3000;
// 1️⃣ Parse JSON bodies
app.use(express.json());
// 2️⃣ Simple logger middleware
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next(); // Pass control to the next middleware/route
});
// 3️⃣ A basic route
app.get('/', (req, res) => {
res.send('Hello, Express!');
});
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
Run node index.js and visit http://localhost:3000. You’ll see the log message in your terminal and “Hello, Express!” in the browser.
Routing Basics
Routes tell Express what to do for a given URL path and HTTP verb (GET, POST, etc.). Here’s a quick cheat sheet:
app.get(path, handler)– read dataapp.post(path, handler)– create dataapp.put(path, handler)– update dataapp.delete(path, handler)– delete data
Routes can be grouped with express.Router() for clean, modular code.
Using a Router: Todo API Example
// routes/todos.js
const express = require('express');
const router = express.Router();
let todos = [
{ id: 1, title: 'Learn Express', completed: false },
{ id: 2, title: 'Build an API', completed: false }
];
// GET /todos – list all
router.get('/', (req, res) => {
res.json(todos);
});
// POST /todos – add new
router.post('/', (req, res) => {
const { title } = req.body;
const newTodo = { id: todos.length + 1, title, completed: false };
todos.push(newTodo);
res.status(201).json(newTodo);
});
// PUT /todos/:id – update a todo
router.put('/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const todo = todos.find(t => t.id === id);
if (!todo) return res.sendStatus(404);
todo.completed = !todo.completed;
res.json(todo);
});
module.exports = router;
Now wire it into your main app:
const express = require('express');
const todoRoutes = require('./routes/todos');
const app = express();
const PORT = 3000;
app.use(express.json());
app.use('/todos', todoRoutes); // All routes start with /todos
app.listen(PORT, () => console.log(`API running at http://localhost:${PORT}`));
Try hitting GET http://localhost:3000/todos with a tool like Insomnia or curl and watch the JSON appear.
Advanced Middleware: Auth + Error Handling
Real apps need security. Let’s add a simple “auth” middleware that checks a custom header.
// middleware/auth.js
module.exports = function (req, res, next) {
const token = req.headers['x-access-token'];
if (token === 'secret123') {
next(); // Authorized
} else {
res.status(401).json({ error: 'Unauthorized' });
}
};
Use it on the todo routes:
const auth = require('../middleware/auth');
router.use(auth); // All /todos endpoints now require the token
For error handling, create a catch‑all middleware at the end of your file:
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
});
Actionable Takeaways
- Start every Express app with
express.json()to parse JSON bodies. - Keep middleware simple: one job, one line. It makes debugging easier.
- Use
express.Router()for large projects. It keeps routes readable. - Stack middleware in the order you want it to run. Order matters!
- Always add a global error handler at the bottom of your middleware stack.
Express middleware and routing are the backbone of any Node.js web app. With a few lines of code and a clear structure, you can build fast, maintainable APIs that feel like a breeze. Happy coding!

