MIGRATION: middleware.ts to proxy.ts
Overview
Next.js 16 renames middleware.ts to proxy.ts and the middleware export to proxy . This is a breaking change with security implications (CVE-2025-29927).
Why This Change Matters
CVE-2025-29927: Middleware-based authentication is fundamentally broken in Next.js. Middleware cannot reliably protect routes because:
-
Middleware runs at the edge, but authentication state lives in databases/sessions
-
Race conditions between middleware checks and route handlers
-
Middleware can be bypassed through direct route access
-
Edge runtime limitations prevent proper session verification
The rename to "proxy" clarifies that this API is for request/response manipulation, not security.
Migration Steps
- Rename the File
Old location
src/middleware.ts
New location
src/proxy.ts
- Rename the Export
Before (Next.js 15):
export function middleware(request: NextRequest) { return NextResponse.next(); }
export const config = { matcher: ['/api/:path*', '/dashboard/:path*'], };
After (Next.js 16):
export function proxy(request: NextRequest) { return NextResponse.next(); }
export const config = { matcher: ['/api/:path*', '/dashboard/:path*'], };
- Update Configuration
If using next.config.js or next.config.ts :
const nextConfig = { experimental: { }, };
No configuration changes needed for proxy. The framework detects proxy.ts automatically.
Security Migration
If you were using middleware for authentication, you must migrate to route-level protection.
Before (Insecure)
export function middleware(request: NextRequest) { const token = request.cookies.get('auth-token');
if (!token) { return NextResponse.redirect(new URL('/login', request.url)); }
return NextResponse.next(); }
export const config = { matcher: ['/dashboard/:path*'], };
After (Secure)
proxy.ts:
export function proxy(request: NextRequest) { const response = NextResponse.next();
response.headers.set('x-custom-header', 'value');
return response; }
app/dashboard/layout.tsx:
import { redirect } from 'next/navigation'; import { verifySession } from '@/lib/auth';
export default async function DashboardLayout({ children, }: { children: React.ReactNode; }) { const session = await verifySession();
if (!session) { redirect('/login'); }
return <>{children}</>; }
Key differences:
-
Authentication logic moves to Server Components
-
Session verification happens in the same runtime as data access
-
No race conditions between auth check and data fetch
-
Can access database/session store reliably
Valid Use Cases for proxy.ts
Use proxy.ts for:
Request/response header manipulation
export function proxy(request: NextRequest) { const response = NextResponse.next(); response.headers.set('x-frame-options', 'DENY'); return response; }
Request logging/monitoring
export function proxy(request: NextRequest) {
console.log(${request.method} ${request.url});
return NextResponse.next();
}
URL rewriting
export function proxy(request: NextRequest) { if (request.nextUrl.pathname === '/old-path') { return NextResponse.rewrite(new URL('/new-path', request.url)); } return NextResponse.next(); }
Geolocation routing
export function proxy(request: NextRequest) { const country = request.geo?.country; if (country === 'US') { return NextResponse.rewrite(new URL('/us', request.url)); } return NextResponse.next(); }
Do NOT Use proxy.ts For
-
Authentication/authorization checks
-
Session validation
-
Database queries
-
Complex business logic
-
Rate limiting (use route handlers instead)
Migration Checklist
-
Rename middleware.ts to proxy.ts
-
Rename middleware export to proxy
-
Remove authentication logic from proxy
-
Move authentication to Server Components/Route Handlers
-
Test that routes are properly protected
-
Verify edge cases (direct route access, API routes, etc.)
-
Update tests that reference middleware
Common Errors
Error: "middleware is not exported"
You forgot to rename the export from middleware to proxy .
Error: "proxy is not a function"
Ensure you're exporting a function named proxy , not a default export.
Error: "Cannot access database in proxy"
Proxy runs at the edge runtime. Move database access to route handlers or Server Components.
Additional Resources
-
CVE-2025-29927: Next.js Middleware Authentication Vulnerability
-
Next.js 16 Migration Guide: Proxy API
-
Next.js Security Best Practices: Route-Level Protection