Next.js Middleware
Run code before requests complete for auth, redirects, and headers
Overview
Middleware runs at the edge before a request reaches your routes. Place middleware.ts at the project root (or src/). Use it for authentication gates, geolocation redirects, A/B tests, and rewriting URLs.
Syntax / Usage
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const token = request.cookies.get('session')?.value
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: ['/dashboard/:path*', '/api/protected/:path*'],
}
Examples
Add security headers:
export function middleware(request: NextRequest) {
const response = NextResponse.next()
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-Content-Type-Options', 'nosniff')
return response
}
Locale prefix rewrite:
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl
if (pathname.startsWith('/en') || pathname.startsWith('/es')) {
return NextResponse.next()
}
return NextResponse.redirect(new URL(`/en${pathname}`, request.url))
}
Common Mistakes
- Running heavy database logic in middleware—keep it fast
- Overly broad
matcherpatterns hitting static assets unnecessarily - Assuming Node.js APIs are available—middleware runs on the Edge runtime
- Infinite redirect loops when auth and login paths overlap
See Also
routing api-routes app-router metadata