Skip to content

fig. Bnextjs

Next.js 16 proxy.ts: What Replaced middleware.ts and How to Migrate

Next.js 16 renamed Middleware to Proxy. See what changed, what the Node.js runtime means for you, how to migrate in one command, and what not to put in it.

Written by
Mayank Panchal
Published
Reading time
3 min
Filed under
nextjs
  • nextjs
  • proxy
  • migration
On this page · 7
  1. Why the rename
  2. Migrating in one command
  3. The catch: Node.js runtime only
  4. What belongs in a proxy
  5. What does not belong in a proxy
  6. Keep it tidy
  7. Checklist

If you open a Next.js 16 project and look for middleware.ts, you will find a deprecation notice instead. Middleware is now called Proxy, and the file is proxy.ts. The rename is not cosmetic noise: it comes with a runtime change that decides whether you can migrate today.

Why the rename#

The Next.js docs say the new name "better reflects its purpose". Middleware suggested something that sat inside your app logic, like Express. What this file actually does is run at the network boundary, before a request is completed, and rewrite, redirect, or respond to it. "Proxy" says that.

The functionality is the same: you still receive a request and can rewrite, redirect, change headers, or answer directly.

Migrating in one command#

Bash
npx @next/codemod@latest middleware-to-proxy .

The codemod renames middleware.ts to proxy.ts, renames the exported function from middleware to proxy, and renames the config options that carried the old name (for example skipMiddlewareUrlNormalize becomes skipProxyUrlNormalize). You can do it by hand just as easily:

TypeScript
// proxy.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function proxy(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}

export const config = {
  matcher: '/about/:path*',
}

A default export works too, but a named proxy export is what the docs recommend.

The catch: Node.js runtime only#

This is the part to read before you run the codemod. The edge runtime is not supported in proxy. Proxy runs on the Node.js runtime and you cannot configure that.

  • If your middleware does not depend on the edge runtime, migrate.
  • If it does, keep using middleware for now. The deprecated convention still works, and the upgrade guide says edge guidance will follow in a later minor release.

What belongs in a proxy#

Good fits:

  • Setting or modifying headers across many routes
  • Rewrites for A/B tests and experiments
  • Redirects that depend on request properties such as a cookie, header, or path

For a plain redirect that never looks at the request, use the redirects option in next.config instead. It is simpler and needs no code to run.

What does not belong in a proxy#

Two warnings come straight from the docs:

  1. Not for slow data fetching. Proxy sits in front of every matched request, so latency here is paid everywhere. Using fetch caching options such as next.revalidate or next.tags inside it has no effect.
  2. Not a full authorization layer. It is fine for an optimistic check, like redirecting when a session cookie is missing:
TypeScript
export function proxy(request: NextRequest) {
  const hasSession = request.cookies.has('session')

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

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

That check only proves a cookie exists. Verify the session itself close to the data, in your server components, route handlers, or server actions, where a bypass can't expose anything.

Keep it tidy#

Only one proxy.ts file is supported per project. If the logic grows, split it into modules and import them into that one file, rather than letting it become a single 400-line function.

Checklist#

  • Does anything rely on the edge runtime? If yes, stay on middleware for now.
  • Run the codemod, then review the diff.
  • Narrow matcher so the proxy does not run on static assets.
  • Move any real authorization out of the proxy and next to your data.

Written by

Mayank Panchal

Software Developer & Full-Time Learner. Coding on the clock, learning around the clock. Software developer in Bengaluru - Next.js, FastAPI, PostgreSQL, AI-native tooling.

fig. B.1keep reading

fig. B.2contact

Let’s build something sharp.