Controlling Requests Before the Cache with Vercel Edge Middleware
Use Vercel Edge Middleware to rewrite, redirect, or add headers before requests reach your Next.js app, with limits on runtime and metering.
01 Sept 2025, 06:52 UTC

Where middleware runs in the request lifecycle
Vercel Edge Middleware executes on the Edge Network before a request reaches static assets or serverless functions. It receives a standard Request object and can return a Response, allowing rewrites, redirects, header changes, and cookie checks. The code runs in the Edge Runtime, which supports a subset of web APIs such as URL, Request, Response, and cookies. Node.js built-ins such as fs and http are unavailable, and most npm packages will not work.
You configure which paths middleware handles with a matcher pattern. Without a matcher, middleware can run on more routes than intended, adding latency to every request.
Worked example: redirect visitors by country
This example sends traffic from Canada to a /ca subpath. Create middleware.ts at your project root, or inside src if your project uses that layout.
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};
export function middleware(request: NextRequest) {
const country = request.headers.get('x-vercel-ip-country');
const pathname = request.nextUrl.pathname;
if (country === 'CA' && !pathname.startsWith('/ca')) {
return NextResponse.redirect(new URL('/ca', request.url));
}
return NextResponse.next();
}
Vercel injects x-vercel-ip-country based on the connecting IP. The matcher excludes Next.js static assets so middleware does not run on CSS, JavaScript, or image requests.
Commands and checks
- Where to run: Terminal in your project root.
- Permissions: Vercel CLI installed and logged in (
vercel login), and the project linked (vercel link) if deploying from the CLI. - Local test: Run
vercel devand visithttp://localhost:3000/. You can confirm path matching, but simulating the geo header locally is unreliable. - Deploy: Push to your connected Git branch, or run
vercel --prod. - Expected check: Run
curl -I https://your-project.vercel.app/. When the geo header is present, expect a307response with aLocationheader pointing to/ca. - Risk: Middleware runs on every matching request, so slow or heavy logic increases latency for all visitors.
Limits and what middleware cannot do
- Edge Runtime restrictions: No
fs,http, or most npm packages. Use standard web APIs orfetch. - No direct database access: Call an API route or use an edge-compatible client instead of connecting to a database from middleware.
- Geo headers are hints, not guarantees:
x-vercel-ip-countrycan be absent or less reliable for VPN and proxy traffic. - Metered usage: Middleware invocations count as Edge Requests. Quotas vary by Hobby, Pro, and Enterprise plans and can change.
- Cache is not automatic: Headers set by middleware do not by themselves enable edge caching. Cache behavior still depends on
Cache-Control, ISR, or stale-while-revalidate settings.
Verify the result and roll back
After deploying, open the Vercel dashboard, select your project, and go to Functions > Logs. Confirm middleware invocations appear and check for errors. Then run curl -I https://your-project.vercel.app/ against a path covered by your matcher and verify the redirect or custom header.
Because adding middleware.ts is a code change, roll back by reverting the file in Git and redeploying. If you deployed with the Vercel CLI, vercel rollback can return to the previous deployment on a linked project.
Practical closing
Start with a narrow matcher so middleware stays off static assets, monitor Edge Requests in your project settings, and keep the handler under a few milliseconds. If your logic needs a database or the file system, move it to an API route or server component instead of forcing it into middleware.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.