Geo-Redirect Users at the Edge with Vercel + ApogeoAPI in 10 Lines
If you serve users in multiple regions, geo-routing is one of those features that sounds complicated but is actually trivial on Vercel. Vercel's Edge Network already knows which datacenter is closest to the visitor — what's missing is enriching that with country / city / currency data so you can do something useful with it.
This tutorial: 10 lines of middleware that intercept every request, look up the visitor's country, and rewrite the URL to a locale-specific path. No client-side flicker, no double network round-trip.
Why edge instead of client-side?
The naive approach is detecting country in the browser via fetch() to your geo API after the page loads. Two problems:
- Layout shift. The page renders in English, then 200ms later swaps to Spanish. Users notice.
- Wasted server work. If the rendered page is per-locale, you're rendering the wrong one first.
Edge middleware runs before the page renders, so the response that hits the browser is already correct.
The middleware (10 lines)
Save this as middleware.ts at the root of your Next.js project:
import { NextRequest, NextResponse } from 'next/server';
export const config = { matcher: '/((?!_next|api|.*\\..*).*)' };
export async function middleware(req: NextRequest) {
const ip = req.ip ?? req.headers.get('x-forwarded-for')?.split(',')[0] ?? '';
if (!ip) return NextResponse.next();
const res = await fetch(`https://api.apogeoapi.com/v1/ip/${ip}`, {
headers: { 'X-API-Key': process.env.APOGEOAPI_KEY! },
next: { revalidate: 3600 }, // cache by IP for 1h
});
if (!res.ok) return NextResponse.next();
const { country } = await res.json();
const locale = countryToLocale(country.iso2); // your mapping
const url = req.nextUrl.clone();
if (!url.pathname.startsWith(`/${locale}`)) {
url.pathname = `/${locale}${url.pathname}`;
return NextResponse.rewrite(url);
}
return NextResponse.next();
}
function countryToLocale(iso2: string): string {
const map: Record = {
AR: 'es', MX: 'es', ES: 'es',
FR: 'fr', BE: 'fr',
DE: 'de', AT: 'de',
};
return map[iso2] ?? 'en';
}
How it actually works on Vercel
The matcher config tells Vercel which paths to run middleware on. We exclude _next/* (Next.js internals), /api/* (no need to geo-redirect APIs), and any URL with a file extension (images, fonts).
The next: { revalidate: 3600 } option caches the geo lookup at the Vercel edge for 1 hour per IP. So a returning visitor doesn't re-hit ApogeoAPI on every request — your API quota is preserved and latency stays near zero on repeat visits.
Adding live exchange rates to the same flow
If your app shows prices, fetch the country's currency rate alongside in the same middleware call. ApogeoAPI bundles it inline:
const res = await fetch(`https://api.apogeoapi.com/v1/countries/${country.iso2}`, {
headers: { 'X-API-Key': process.env.APOGEOAPI_KEY! },
next: { revalidate: 14400 }, // 4h matches FX cache
});
const { currency, currencyRate } = await res.json();
// Inject into response headers — your page reads from these
const response = NextResponse.rewrite(url);
response.headers.set('x-user-country', country.iso2);
response.headers.set('x-user-currency', currency);
response.headers.set('x-user-fx-rate', String(currencyRate));
return response;
Now any Server Component can read those headers via headers() and render localized prices in the user's currency without a second roundtrip.
Cost considerations
Vercel Edge Middleware is free up to 1M invocations / month on the Hobby plan. ApogeoAPI's free tier is 1,000 calls / month. That's enough for a project at the early-traction stage. With Vercel's edge caching at 1h, you only burn API quota once per IP per hour — typical usage stays under quota even with thousands of daily visitors.
Common gotchas
- Localhost.
req.ipis empty in dev. Hardcode an IP for testing or use ngrok. - VPN visitors. Geolocation reflects the VPN exit node, not the user's actual country. Acceptable for most apps, not for fraud detection.
- Cookies. If you let users override the auto-detected locale (a "Switch to English" button), set a cookie and check it before geo-detecting.
Live demo
Visit apogeoapi.com/demo and ask the AI agent: "What country am I from?". It runs the same kind of edge lookup and returns the answer in under 200ms. Source code for the demo is in our public repo.
Get a free ApogeoAPI key at apogeoapi.com — 1,000 requests / month, no credit card.
Try ApogeoAPI free
1,000 requests/month forever. 14-day full-access trial. No credit card.
Get your free API key