Script Valley
Next.js: Full-Stack React Applications
Routing, Navigation, and Dynamic SegmentsLesson 2.5

How middleware works in Next.js and when to use it

middleware.ts, NextResponse, request inspection, redirects in middleware, route matching with matcher, auth guards, edge runtime

What Middleware Does

Middleware runs before a request reaches your routes. It executes at the edge, before the page renders. Use it for: authentication guards, redirects, A/B testing header injection, and rate limiting headers.

// middleware.ts (in project root, NOT inside /app)
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const token = request.cookies.get('auth-token')

  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/dashboard/:path*', '/settings/:path*'],
}

The matcher Config

The matcher array controls which paths trigger your middleware. Without it, middleware runs on every request including static assets — a significant performance hit. Be explicit with patterns.

What Middleware Cannot Do

Middleware runs in the Edge Runtime, which is a subset of Node.js. You cannot use Node.js APIs like fs, most npm packages that depend on Node internals, or Prisma/database clients. For complex auth logic, middleware should only check for the presence of a cookie or token, not validate it with a database call — do that in the route itself.