Understanding Middleware in Next.js
Next.js is a popular React framework that simplifies building modern web applications. One of its powerful features is Middleware, which allows you to execute custom logic before a request is completed. Let’s break down what Middleware is, how it works, and the practical use cases it can solve.
What is Middleware in Next.js?
Middleware in Next.js allows you to intercept incoming requests and execute custom logic before routing occurs. Think of it like a security checkpoint for your web app — you can decide what happens to each request.
Common Use Cases:
- Redirect users who are not logged in
- Modify headers for security
- Rewrite URLs dynamically for SEO
- Handle requests based on location or device
Example:
import { NextResponse } from 'next/server';
export function middleware(request) {
const url = request.nextUrl.clone();
if (!url.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
This example redirects users to the login page if they try to access routes outside of /dashboard.
How Middleware Works
Middleware runs before the request reaches the actual route. It is deployed at the edge (close to the user), enabling fast operations like redirects and rewrites with minimal delay.
Middleware Flow:
- Client sends a request
- Middleware intercepts and applies logic (e.g., redirect, rewrite, headers)
- Edge network or static content is served
- Middleware response time is usually 10–50ms, making it ideal for fast request handling.
Adding Middleware to Specific Routes
You don’t need middleware for every route. You can scope middleware using the matcher option in next.config.js.
Example:
module.exports = {
experimental: {
middleware: {
matcher: ['/dashboard/:path*'], // Runs only on dashboard routes
},
},
};
This improves performance by running middleware only where needed.
Use Cases of Middleware
- Handling Custom Headers:
You can dynamically modify request/response headers.
export function middleware(request) {
const response = NextResponse.next();
response.headers.set('X-Custom-Header', 'MyValue');
return response;
}
Use cases:
- Add security headers
- Add analytics tracking
- Dynamic URL Rewrites:
You can rewrite URLs on the fly without changing client-side routes.
export function middleware(request) {
const url = request.nextUrl.clone();
if (url.pathname === '/old-route') {
url.pathname = '/new-route';
return NextResponse.rewrite(url);
}
return NextResponse.next();
}
Use cases:
- SEO-friendly URLs
- Managing legacy routes
- Combining Middleware with Edge Functions
Since middleware runs at the edge, it’s ideal for real-time personalization based on location or device.
export async function middleware(request) {
const geo = request.geo; // Geolocation data
console.log(
Request from ${geo.city}, ${geo.country});
return NextResponse.next();
}
Use cases:
- Show location-based content
- Device-aware experiences
Benefits of Using Middleware
- Performance: Executes close to users, reducing latency
- Customization: Apply logic per route or user
- SEO-Friendly: Rewrite routes for better search indexing
- Security: Add headers, auth checks, log requests
- Real-Time Handling: Personalize based on context
Conclusion
Middleware in Next.js is a powerful tool for:
- Custom logic before routing
- Dynamic rewrites and redirection
- Header management and route-level security
Whether you're improving security, optimizing for performance, or personalizing content, Middleware gives you the control you need — fast, flexible, and simple. Give it a try in your next Next.js project!