Skip to content

Build1 publisher2 min readPublished

Next.js 16 renames middleware.ts to proxy.ts, which always runs on the Node.js runtime

Next.js 16 kept middleware.ts working after renaming the convention to proxy.ts, so clean upgrades hid the change. The new file runs on Node.js only, and a runtime export copied across during migration is ignored.

The Engineer · Build desk

Illustration accompanying Next.js 16 renames middleware.ts to proxy.ts, which always runs on the Node.js runtime

What happened

  • Next.js 16 renamed the middleware.ts convention to proxy.ts; the old file still runs, and a dev.to walkthrough calls it the deprecated way to check a request before any app code executes.
  • An export const runtime = "edge" line carried into proxy.ts during a migration is ignored, and the file keeps running on Node.js without erroring.
  • The boundary file runs on every request matching its matcher, before the App Router resolves a route and before any layout, page, Server Component or Server Action executes.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • capability Auth code written under the Edge constraint can now use a Node-only JWT library or open a database connection at the boundary, and it will do so on every matched request ahead of the router.
  • cost Teams whose upgrade broke nothing deferred the work, and the work falls to whoever next touches the repo: a codemod run plus a read of every runtime export in the boundary file.
  • decision A repo where new proxy.ts files are landing beside an old middleware.ts has to standardise on one name, because the split shows up in what developers believe about the runtime, not in the build output.

A request that matches the matcher reaches proxy.ts before the App Router resolves a route, which is to say before any layout, page, Server Component or Server Action runs [6]. The position is the one middleware.ts held. The runtime beneath it is fixed at Node.js, and a dev.to walkthrough of the convention states that it cannot be configured [3].

So the config line to grep for in a half-finished migration is `export const runtime = "edge"`. Inside proxy.ts it does nothing: the file runs on Node.js regardless and does not fail loudly [4]. The line looks exactly like the one that was there before, so review misses it.

Under Next.js 15 the restricted Edge runtime is what forced the dependency choices in boundary code, including jose instead of jsonwebtoken, no direct database calls and no `fs` [7]. Those restrictions came from the runtime, so under proxy.ts a Node-only library or a direct database client is available [15]. The same file still runs on every request the matcher catches [6].

The walkthrough is less consistent about what choice was taken away. Its Next.js 15 sample annotates the Edge runtime as "the only option" [9], while one of its stated objectives is to explain "which runtime proxy.ts runs on" and "why you can no longer choose" [10]. A reader cannot settle that from the article. What both halves agree on is the operative fact for a migration: the boundary now runs on Node.js and you do not set it [3].

The move itself is a codemod. Next.js ships an official one, and it renames the config options that changed alongside the file [5]. The hazard the author describes is the interim state, where new files copied from the docs or a teammate's project land as proxy.ts while the old middleware.ts is still present, leaving two names for one job [11]. The rename was deliberate on the framework's side: according to the walkthrough, Next.js 16 changed the name specifically to stop developers treating the file as an Express-style request handler in a chain [14].

The article is written against Next.js 16.3, which it describes as the current Active LTS release, verified against the framework's own file-convention and upgrade docs and its GitHub releases in September 2026 [2]. The author's instruction to readers on a much later version is to re-check the linked docs before trusting a specific detail [12]. Good habit, and rare in a tutorial. The piece also lists "the one capability trade Next.js made" as something a reader should be able to recognise [13]; the text available stops before that section.

What to watch

  • Whether a later 16.x release attaches a build-time deprecation warning or a removal version to middleware.ts.
  • How the official codemod behaves on a repo that already contains both a middleware.ts and a proxy.ts.
  • The capability trade the walkthrough flags: what proxy.ts can no longer do that Edge middleware could.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories