Dev Encyclopedia
ArticlesToolsContactAbout

Get notified when new content drops

No spam. Just new articles, tools, and updates straight to your inbox.

Dev Encyclopedia

A reference for builders

Content

  • Articles
  • Tools
  • About
  • Contact

Connect

  • support@devencyclopedia.com
  • RSS Feed

Legal

  • Privacy Policy
  • Terms of Service
  • Disclaimer

© 2026 Dev Encyclopedia

Back to top ↑
  1. Home
  2. /Blog
  3. /Next.js middleware.ts to proxy.ts: What Changes
nextjs11 min read

Next.js middleware.ts to proxy.ts: What Changes

Next.js 16 renamed middleware.ts to proxy.ts, and it's not just a name change. Here's what the runtime switch means and how to migrate a real auth-check file.

Zeeshan Tofiq
Zeeshan Tofiq
July 1, 2026
On this page

On this page

  • The Rename Isn't Cosmetic
  • Why the Default Runtime Change Matters
  • Migrating middleware.ts to proxy.ts: Step by Step
  • Rename the file
  • Rename the export and switch to a default export
  • Confirm imports and config are untouched
  • Test the route locally before deploying
  • A Real Example: Migrating Auth-Check Middleware
  • What Breaks If You Used Edge-Only APIs
  • Should You Migrate Now or Wait?
  • Frequently Asked Questions

Next.js 16 renamed middleware.ts to proxy.ts. If you skimmed a "what's new in Next.js 16" roundup, you probably saw this mentioned in a single bullet point next to Cache Components and Turbopack. It deserves more attention than that, because the rename comes bundled with a real architectural change: proxy.ts runs on the Node.js runtime by default, not the Edge runtime that middleware.ts used.

This guide covers exactly what changes, why the runtime default matters, and how to migrate a real middleware file with auth checks and redirects, step by step.

The Rename Isn't Cosmetic

Three things change together when you move from middleware.ts to proxy.ts, and only one of them is cosmetic:

  1. The filename — middleware.ts becomes proxy.ts at the project root
  2. The exported function name — the named export middleware becomes a default export proxy
  3. The default runtime — Edge becomes Node.js

The third item is the one that actually matters for your code. middleware.ts still works. Next.js's own release notes confirm it remains available for Edge-runtime use cases, but it's marked deprecated and scheduled for removal in a future major version. This isn't a forced migration today, but it is a deprecation clock worth planning around, especially if your app has more than one middleware-adjacent file.

ℹ Nothing breaks on upgrade

Upgrading to Next.js 16 does not require touching middleware.ts immediately. The file keeps working. The rename only takes effect when you create a new proxy.ts file or explicitly migrate.

Why the Default Runtime Change Matters

Edge runtime gave middleware.ts global low-latency distribution: your logic ran close to the requesting user, everywhere, but with a restricted set of available APIs. No arbitrary Node built-ins, no native modules, and a smaller compatibility surface for third-party packages.

Node.js runtime gives proxy.ts the full Node.js API surface. That removes some of the awkward workarounds Edge runtime forced on you, like swapping a package for a lighter Edge-compatible fork just so your middleware would build. The tradeoff runs the other way too: you lose some of the distribution characteristics Edge provided by default.

Edge Runtime (middleware.ts)Node.js Runtime (proxy.ts default)
Global distributionRuns at edge locations close to the userRuns in your deployment's Node.js runtime
Node.js API accessRestricted subset of Web APIs onlyFull Node.js API surface
Package compatibilityMany Node-only packages fail to buildBroad compatibility with npm packages
Typical use case fitSimple, latency-sensitive checks (geo, A/B routing)Anything needing full Node APIs or heavier logic
Still available in Next.js 16?Yes, via middleware.ts (deprecated)Yes, the new default via proxy.ts

If your middleware does something simple like checking a cookie, redirecting unauthenticated users, or rewriting a header, this distinction barely shows up in practice. If your middleware specifically depended on Edge runtime's geographic distribution for latency-sensitive logic, or used Edge-only Web APIs that don't behave identically under Node.js, that's the part to test carefully before migrating. If you're also cleaning up how your app reads configuration during this upgrade, it's worth revisiting how environment variables work in Next.js at the same time, since middleware is one of the few places server-only and public variables both come into play at request time.

Migrating middleware.ts to proxy.ts: Step by Step

  1. 1

    Rename the file

    Rename middleware.ts at your project root to proxy.ts. The file's location doesn't change, only the name. Next.js looks for proxy.ts first and falls back to middleware.ts if it's not present, so having both at once will cause Next.js to prefer proxy.ts.

    bash
    mv middleware.ts proxy.ts
  2. 2

    Rename the export and switch to a default export

    Change the named export middleware to a default export named proxy. This is the part that trips people up if they only skim the docs: it's not just a rename, the export style changes from named to default.

    typescript
    // Before
    export function middleware(request: NextRequest) { ... }
    
    // After
    export default function proxy(request: NextRequest) { ... }
  3. 3

    Confirm imports and config are untouched

    NextRequest and NextResponse imports don't change. Your matcher config, if you have one, is exported the same way it always was. The migration is deliberately narrow: file name, function name, export style. Everything else in a typical auth or redirect middleware stays identical.

    💡 Tip

    If your editor's auto-import quietly reverted the default export back to a named one, double check the export line before moving on. TypeScript won't error on a named proxy export, but Next.js won't pick it up as the route handler.

  4. 4

    Test the route locally before deploying

    Run next dev and exercise every path your matcher covers: an authenticated request, an unauthenticated one, and any redirect or rewrite branch. For most auth-check or header-rewrite middleware, this is where the migration ends. If your file only touches cookies, headers, and redirects, you're done.

    bash
    next dev
    # then manually hit the protected routes covered by your matcher

A Real Example: Migrating Auth-Check Middleware

Here's a realistic middleware.ts file that checks a session cookie and redirects unauthenticated users away from a protected route:

typescript — middleware.ts (Next.js 15 and earlier)
import { NextRequest, NextResponse } from 'next/server'

export function middleware(request: NextRequest) {
  const session = request.cookies.get('session')

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

  return NextResponse.next()
}

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

The Next.js 16 equivalent, after migration:

typescript — proxy.ts (Next.js 16+)
import { NextRequest, NextResponse } from 'next/server'

export default function proxy(request: NextRequest) {
  const session = request.cookies.get('session')

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

  return NextResponse.next()
}

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

Notice what didn't change: the NextRequest/NextResponse imports, the cookie-checking logic, and the matcher config export. What changed: the filename, the function name, and export default in place of a named export function. For middleware this simple, the migration genuinely is a five-minute rename-and-test.

💡 Skip the manual rename

Convert your own middleware.ts file instantly with MiddlewareToProxy, it rewrites the export for you and flags any Edge-runtime-specific lines worth reviewing first.

What Breaks If You Used Edge-Only APIs

If your middleware does anything beyond cookie and header logic, don't migrate blindly. A handful of patterns are common enough to call out specifically before you move a real production file.

Common Edge-specific middleware patterns and what to check before migrating
If your middleware does thisRisk under proxy.ts's Node.js runtimeWhat to do
Reads geo-IP headers for latency-sensitive routingBehavior may differ since the code no longer runs at the edge location closest to the userBenchmark latency on proxy.ts before switching production traffic
Imports an Edge-only or WASM-based libraryMay now work under Node.js, or may need a different package entirelyTest the import path directly rather than assuming compatibility either way
Uses `process.env` dynamic key accessNo change in behavior; this was already a Next.js compile-time limitation, not an Edge-specific oneNo action needed for this specific concern
Streams a response body directly from middlewareNode.js runtime handles streaming differently than Edge runtime internalsManually verify streamed responses in a staging environment
Connects directly to a database or external serviceWas likely already awkward under Edge; Node.js runtime removes most of that frictionThis is usually a safe case to migrate, and often an improvement

⚠ Warning

For these cases, Next.js's deprecation path explicitly keeps middleware.ts available during the transition. There's no requirement to migrate immediately just because proxy.ts exists. The removal of middleware.ts support lands in a future version, not the current one. Use the time to test thoroughly rather than rushing a migration that changes runtime behavior.

Should You Migrate Now or Wait?

The answer depends entirely on what your middleware actually does, not on how new proxy.ts is.

  • Middleware only checks cookies, headers, or does simple redirects: migrate now
  • Middleware relies on Edge-specific geo-distribution for latency: benchmark on proxy.ts in a branch first
  • Middleware imports a package that previously required an Edge-compatible fork: test the standard package under proxy.ts
  • You're mid-migration and can't test every code path today: stay on middleware.ts, it's still supported
  • You're starting a new project on Next.js 16: use proxy.ts from day one, there's no reason to start on the deprecated path

Simple middleware, meaning auth checks, redirects, header rewrites, A/B test cookie routing, should migrate now. It's a small, low-risk change and gets you off the deprecation path early. Complex middleware relying on Edge-specific behavior should get tested on proxy.ts in a branch first, with latency benchmarked if that mattered to your use case, and only promoted to production once behavior is confirmed to match. Staying on middleware.ts during that evaluation window is the safer choice since it's explicitly still supported, just deprecated.

If this migration is part of a broader Next.js 16 upgrade, it's also worth checking your CI build pipeline for anything that references middleware.ts by name, like custom lint rules or file-existence checks, so the rename doesn't silently break a build step nobody's looking at. And if you're evaluating whether to stay on Next.js at all for a given project, our Next.js to TanStack Start migration breakdown covers the tradeoffs from the other direction.

Frequently Asked Questions

Is middleware.ts deprecated in Next.js 16?

Yes, but it still works. Next.js 16 introduces proxy.ts as the replacement and continues to support middleware.ts for Edge-runtime use cases during a deprecation window. It's scheduled for removal in a future major version, not the current one.

What is proxy.ts in Next.js?

proxy.ts is the Next.js 16 replacement for middleware.ts. It lives at the project root, exports a default function named proxy instead of a named middleware function, and runs on the Node.js runtime by default instead of the Edge runtime.

  • Same purpose — intercepts requests before they reach a route, for auth checks, redirects, and header rewrites
  • Different export — default export proxy, not named export middleware
  • Different default runtime — Node.js instead of Edge
Does proxy.ts run on Edge or Node.js runtime?

proxy.ts runs on the Node.js runtime by default. This is the core behavioral difference from middleware.ts, which defaulted to the Edge runtime. Check the current Next.js documentation for the explicit Edge-runtime opt-in if you need to preserve that behavior for a specific file.

How do I migrate middleware.ts to proxy.ts?
  1. Rename the file — middleware.ts becomes proxy.ts
  2. Change the export — the named export function middleware becomes export default function proxy
  3. Leave imports and config alone — NextRequest, NextResponse, and the matcher config export stay the same
  4. Test locally — run next dev and exercise every path covered by your matcher before deploying

💡 Tip

See the step-by-step walkthrough and before/after code example earlier in this article for the full migration with a realistic auth-check file.

Will my existing middleware.ts file break after upgrading to Next.js 16?

No. Upgrading Next.js to version 16 does not require any changes to an existing middleware.ts file. It continues to run exactly as before. The rename only becomes relevant when you choose to create a proxy.ts file or explicitly migrate the existing one.

Can I still use Edge runtime with proxy.ts?

The default runtime for proxy.ts is Node.js, but Edge runtime hasn't disappeared from Next.js entirely, it's just no longer the default for this specific file. If your use case genuinely depends on Edge-runtime characteristics, check the current Next.js documentation for the explicit runtime configuration, or keep the logic on middleware.ts during the deprecation window while that behavior is fully preserved.

middleware.ts vs proxy.ts: what's the actual difference?
middleware.tsproxy.ts
Export styleNamed export (middleware)Default export (proxy)
Default runtimeEdgeNode.js
Status in Next.js 16Deprecated, still worksCurrent default
Node.js API accessRestrictedFull

Use proxy.ts for anything new. Keep an existing middleware.ts file as-is if it depends on Edge-specific behavior you haven't tested under Node.js yet.

Zeeshan Tofiq

Zeeshan Tofiq

Full Stack Developer

Full stack developer with over 6 years of experience building production applications. Writes practical guides on JavaScript, TypeScript, React, Node.js, and cloud infrastructure. Focused on helping developers solve real problems with clean, maintainable code.

Enjoyed this article?

Get practical dev guides, tool updates, and new articles delivered straight to your inbox. No spam, unsubscribe anytime.

Related Articles

nextjs

How to Use Environment Variables in Next.js (Without Leaking Them to the Browser)

Learn how to use .env files in Next.js correctly. Understand NEXT_PUBLIC_, avoid common mistakes, and set variables in Vercel and Cloudflare.

May 30, 2026·12 min read
react

Migrate Next.js to TanStack Start: Practical Guide with Real Examples

How to migrate a Next.js app to TanStack Start: the two-PR strategy, route migration, replacing next/image, and setting up Nitro, with real production lessons from Railway and Inngest.

Jun 21, 2026·14 min read

On this page

  • The Rename Isn't Cosmetic
  • Why the Default Runtime Change Matters
  • Migrating middleware.ts to proxy.ts: Step by Step
  • Rename the file
  • Rename the export and switch to a default export
  • Confirm imports and config are untouched
  • Test the route locally before deploying
  • A Real Example: Migrating Auth-Check Middleware
  • What Breaks If You Used Edge-Only APIs
  • Should You Migrate Now or Wait?
  • Frequently Asked Questions
Advertisement