How it works
The explanation, with examples you can run.
A typical proxy
// proxy.tsimport { NextResponse, type NextRequest } from "next/server" export function proxy(request: NextRequest) { const hasSession = request.cookies.has("session") if (!hasSession && request.nextUrl.pathname.startsWith("/dashboard")) { const login = new URL("/login", request.url) login.searchParams.set("next", request.nextUrl.pathname) return NextResponse.redirect(login) } const response = NextResponse.next() response.headers.set("x-frame-options", "DENY") return response} export const config = { // everything except API routes, Next.js assets and common static files matcher: ["/((?!api|_next/static|_next/image|favicon.ico|.*\\.png$).*)"],}The matcher is read at build time, so it must be a constant. Only one proxy.ts is allowed; split logic into modules and import them.
What it is good for
- Redirects and rewrites that depend on the request: locale detection, A/B buckets, legacy URLs. (Fixed redirects are simpler in
next.config.ts.) - Headers for many routes at once, such as security headers or a request ID.
- Optimistic auth checks: is there a session cookie at all? Send obvious anonymous traffic to the login page before rendering anything.
What it is not for
Proxy runs on every matched request, so anything slow in it slows every page. It isn't the place for database queries or full session validation, and fetch cache options have no effect inside it. More importantly, it is not an authorisation layer. A page can be reached through a rewrite, a Server Action is a POST to whatever route renders it, and a later change to the matcher pattern can exclude paths you meant to protect without any error. The Data Security guidance is to check authentication and authorisation where data is read or changed: in a data access layer used by Server Components, Route Handlers and Server Actions.
If you were using Middleware with runtime = "edge", note that Proxy does not support the Edge runtime. The upgrade guide says to keep the old middleware file for now if you depend on Edge, but the Edge runtime itself is deprecated for routes in current Next.js, so plan to move that code to Node.js.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.