next.js: [NEXT-696] New middleware slows down routing in production

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System: Platform: win32 Arch: x64 Version: Windows 10 Pro
Binaries: Node: 16.14.2 npm: N/A Yarn: N/A pnpm: N/A Relevant packages: next: 12.2.0 eslint-config-next: 12.2.0 react: 18.2.0 react-dom: 18.2.0

What browser are you using? (if relevant)

Chrome 103.0.5060.66

How are you deploying your application? (if relevant)

next start

Describe the Bug

New middleware slows down on routing in production (dev is okay), example code that slows down:

import { NextResponse } from 'next/server';

const Middleware = (req) => {
  /** To lower case redirect. */
  if (req.nextUrl.pathname === req.nextUrl.pathname.toLowerCase())
    return NextResponse.next();

  return NextResponse.redirect(new URL(req.nextUrl.origin + req.nextUrl.pathname.toLowerCase()));
};

export default Middleware;

Expected Behavior

Work as expected with no slow down, with previous _middleware.js there was no problem

To Reproduce

Create middleware.js file under root folder and use code from example

NEXT-696

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 16
  • Comments: 32 (2 by maintainers)

Most upvoted comments

Has Anyone solved this problem?

Without a fix for this, the framework is basically unusable right now …

The problem also exists in the 13 release. Just the presence of a middleware increases the response time tenfold.

I did a test with a fresh next@canary release and a request to http://localhost:3000/vercel.svg takes 4ms without middleware. The same request with a middleware present, takes 150 - 300ms on my local machine. There seems to be a problem with the middleware loader, as the middleware does not have to do anything to cause that kind of delay.

// middleware.ts

export function middleware() {}

Is enough to drop the response time

I’ve tested this out with: 13.1.6 canary release and its slowing down requests on dev mode (~80ms to 250ms delay per request). But on a production build its not causing any noticeable delay after the first request has been made to the server.

So it appears https://github.com/vercel/next.js/pull/42547 did solve the issue for production only.

However, The delay is still quite disruptive while working on dev.

I understand cache is disabled on the dev build to allow the compiler to catch code changes, but since the middleware.ts code is rarely changed, Would it be wise to provide a config option to force middleware cache in dev mode too?

Adding a matcher to exclude resources helped in my case, of course it depends on your use case, in my case I didn’t need a middleware for api/resources calls:

  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - favicon.ico (favicon file)
     * - assets (static assets)
     */
    '/((?!api|_next/static|favicon.ico|assets).*)'
  ]
};

@ch3rn1k I have the similar issue but the reason (at least for me) is that the pages are being re-rendered if I use middleware.js in the root. I described it here: #38267. Could you please check and confirm if you have the same issue?

Looks same so, but I got no error or slow work when no checks inside, like this:

import { NextResponse } from 'next/server';

const Middleware = (req) => {
 return NextResponse.next();
};

export default Middleware;

@baraeb92 in 13.0.3-canary.1 this still exists.

It may or may not be relevant that the middleware is now re-initialized on each request when in dev mode, rather than being initialized only once and then persisting like in previous versions.

Also seeing this, tried it on 12.3.2 canary and the issue persists, we’re talking massive slowdown. It seems to read many .json files all at once (loading SSR product detail page for example), pending for 10-20 seconds. Everything goes back to normal if middleware.ts is removed.

Everything was normal in the old _middleware.ts which was used in /pages

I understand cache is disabled on the dev build to allow the compiler to catch code changes, but since the middleware.ts code is rarely changed, Would it be wise to provide a config option to force middleware cache in dev mode too?

Similar issues: https://github.com/vercel/next.js/issues/43999 https://github.com/vercel/next.js/discussions/44053

Also having same problem. Wait time is too high. Because of that Web Core Vitals hurting.