why your nextjs middleware is so damn slow - By Sourav Mishra (@souravvmishra)
stop putting database calls in your proxy.ts, please lol.
okeyy, so next.js changed middleware.ts to proxy.ts. the name changed, but folks are still making the same mistakes.
i've seen a hell lot of things kill performance, so let's look at the worst ones.
the edge is lightweight
your proxy runs on the edge. that means:
- no node.js APIs: you can't use
fsor regular node stuff. - super fast: it has to be quick.
- runs on everything: it intercepts every single request by default.
mistake 1: db calls
❌ don't do this: connecting to a database in proxy.ts.
// proxy.ts
import { db } from './lib/db'; // ⚠️ big nope
export async function proxy(req) {
const user = await db.user.find(req.cookies.get('session'));
if (!user) return Response.redirect('/login');
}
why is this so bad?
because opening a db connection adds 200ms+ to every single request. we once fixed a client's site just by removing one db call here—bam, 600ms dropped to 120ms.
✅ do this instead: use simple jwt auth or fast redis calls via http.
mistake 2: forgetting matchers
❌ don't do this: running proxy on images and styles.
// middleware.ts
// oops, no config exported
if you do this, your proxy runs for every css file and image. lol.
✅ do this instead: filter that stuff out.
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};
mistake 3: waiting for geo data
don't waste time looking up IPs from a 3rd party API. just use the geo object next.js gives you.
// proxy.ts
export function proxy(req) {
const country = req.geo?.country || 'US';
// fast logic here
}
what to remember
- rename it: use
proxy.tsnow. - keep it dumb: only use it for routing and basic auth checks.
- fetch later: do real data fetching in
layout.tsxor server components. - use matchers: skip static assets.
if you're pulling your hair out over css, check out how to fix prod css.
written by sourav mishra, just trying to make the web faster.