Running IP geolocation at the edge — at Cloudflare Workers, Vercel Edge Functions, or AWS Lambda@Edge — gives you fast geo decisions with minimal latency. Personalize content, restrict regions, redirect by country, and fingerprint traffic, all without an origin round-trip.
This post is the practical guide: which platforms make geo easy, what data each provides, the patterns for combining with Ip2Geo for richer signals, and the cost/performance trade-offs.
What “At the Edge” Means
Edge platforms run your code in hundreds of POPs around the world. When a user makes a request:
- Request hits the nearest POP (anycast routing).
- Edge code runs at that POP, ~milliseconds away.
- Decision (route, modify, respond) made there.
- Origin called only if needed.
For IP geolocation specifically, “at the edge” means: by the time your code runs, you already know where the user roughly is. The edge platform usually has this data baked in.
For the broader context, see CDN vs edge computing.
Cloudflare Workers
Cloudflare’s edge runtime. Probably the most generous for geo data.
Built-in geo data
Available on every request:
request.cf.country— Country code.request.cf.city— City name.request.cf.region— Region/state.request.cf.latitude,request.cf.longitude— Coordinates.request.cf.timezone— IANA timezone.request.cf.continent— Continent code.request.cf.asn— ASN.request.cf.colo— Cloudflare POP serving this request.
export default {
async fetch(request: Request): Promise<Response> {
const country = request.cf?.country ?? 'US'
const city = request.cf?.city ?? 'Unknown'
return new Response(`Hello from ${city}, ${country}`)
}
}
All this data is free with Cloudflare Workers. No additional API call.
Combining with Ip2Geo
When you need richer data (ASN classification, network type, VPN detection), call the Ip2Geo API from your worker:
const clientIp = request.headers.get('cf-connecting-ip')
const response = await fetch(`https://api.ip2geo.dev/convert?ip=${clientIp}`, {
headers: { 'X-Api-Key': env.IP2GEO_API_KEY }
})
const data = await response.json()
const asnType = data.data?.asn?.type // 'residential', 'mobile', 'hosting', 'vpn'
if (asnType === 'hosting') {
return new Response('Bot detected', { status: 429 })
}
The combination: Cloudflare’s free country/city/timezone + Ip2Geo’s ASN classification = comprehensive edge-side IP intelligence.
Vercel Edge Functions
Vercel’s edge runtime. Similar capabilities to Cloudflare Workers.
Built-in geo data
import { geolocation } from '@vercel/edge'
export default function handler(request: Request) {
const geo = geolocation(request)
// geo.country, geo.city, geo.region, geo.latitude, geo.longitude
return new Response(`Hello from ${geo.city}`)
}
Available on Vercel’s Edge Network. Same minimal-cost pattern as Cloudflare.
Pages with geo
Next.js running on Vercel can use geo in middleware.ts:
import { NextRequest, NextResponse } from 'next/server'
export function middleware(request: NextRequest) {
const country = request.geo?.country ?? 'US'
if (country === 'DE') {
return NextResponse.redirect(new URL('/de', request.url))
}
return NextResponse.next()
}
Per-request edge logic that runs before any page rendering.
AWS Lambda@Edge
AWS’s edge runtime, integrated with CloudFront.
Built-in geo data
Via the CloudFront-Viewer-Country and related headers, available to Lambda@Edge functions:
exports.handler = async (event) => {
const request = event.Records[0].cf.request
const country = request.headers['cloudfront-viewer-country']?.[0]?.value
const city = request.headers['cloudfront-viewer-city']?.[0]?.value
return request
}
CloudFront Functions
A lighter alternative for simple use cases (no async, restricted runtime, smaller cost):
function handler(event) {
var country = event.viewer.country
// routing logic
return event.request
}
Use CloudFront Functions for simple decisions; Lambda@Edge for more complex logic.
Comparison
| Feature | Cloudflare Workers | Vercel Edge Functions | AWS Lambda@Edge |
|---|---|---|---|
| Built-in country | Yes (free) | Yes | Yes |
| Built-in city | Yes | Yes | Yes |
| Built-in ASN | Yes | No | No |
| Built-in timezone | Yes | No | No |
| Cold start | ~0ms | <1ms | 50-100ms |
| Pricing | Per request | Per request | Per request + duration |
| Region coverage | 300+ POPs | Vercel’s network | CloudFront POPs |
Cloudflare has the richest geo data baked in. Vercel and AWS provide country/city but require an API call for ASN.
Common Patterns
Country-based redirect
At the edge, redirect users to a regional URL:
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url)
const country = request.cf?.country ?? 'US'
if (url.pathname === '/') {
const region = countryToRegion(country)
return Response.redirect(`${url.origin}/${region}`, 302)
}
return fetch(request)
}
}
See geo-redirect implementation for the full pattern.
Block by country
For geofencing:
const BLOCKED = new Set(['XX', 'YY'])
const country = request.cf?.country
if (BLOCKED.has(country)) {
return new Response('Not available', { status: 451 })
}
Currency localization
Use country/region to pick currency:
const country = request.cf?.country ?? 'US'
const currency = countryToCurrency(country)
// Inject into response or pass to origin
For more, see currency from IP.
Cache by country
Different cache keys per country:
const cacheKey = new Request(url, {
method: 'GET',
headers: { 'X-Country': request.cf?.country }
})
CDN serves the cached version per country.
Fraud-aware routing
For high-stakes endpoints:
const ip = request.headers.get('cf-connecting-ip')
const isHosting = await isHostingIp(ip, env) // Calls Ip2Geo
if (isHosting && isLoginEndpoint(request)) {
return new Response('Captcha required', { status: 429 })
}
Hosting traffic on login endpoints gets challenged. Real users from residential ASNs pass through cleanly.
Performance Considerations
Edge-side geo decisions are fast:
- Native country/city: 0ms (it’s in the request).
- Ip2Geo API call: typically 30-50ms from a major POP.
For decisions that need ASN/classification, the 30-50ms API call adds latency but eliminates the origin round-trip (which would be much longer). The net is still faster than doing it at origin.
Caching API responses
Cache Ip2Geo lookups per IP at the edge:
const cached = await env.GEO_CACHE.get(clientIp)
if (cached) {
return JSON.parse(cached)
}
const fresh = await fetchIp2Geo(clientIp)
await env.GEO_CACHE.put(clientIp, JSON.stringify(fresh), { expirationTtl: 3600 })
return fresh
Use Cloudflare KV, Vercel KV, or DynamoDB at the edge. Saves API calls; 5-15 min TTL is typical. See caching IP geolocation responses.
Pricing Considerations
Edge platforms charge per request. For high-traffic sites:
- Cloudflare Workers — $0.50 per million requests + $0.50 per million CPU-ms.
- Vercel Edge Functions — Similar.
- AWS Lambda@Edge — $0.60 per million + per-duration.
For a site with 1 billion requests/month doing geo decisions: ~$500-1000/month in edge compute. Cheap compared to the time saved.
Adding Ip2Geo for richer signals: per-call cost, depends on tier. Free tier is 1000 lookups/month — fine for prototyping.
When NOT to Use Edge
A few cases where edge geo decisions don’t apply:
Static cached content
A fully-cached page doesn’t need to make a decision per request. The CDN serves the cached version directly.
Heavy origin logic
If the bulk of processing happens at origin anyway, doing geo at the edge is marginal.
Compliance requires origin processing
Some regulations require certain decisions to happen in specific regions. Edge POPs might not satisfy this.
For most modern apps, though, “do the geo check at the edge” is the right default.
Composition: Edge + Origin
A typical pattern uses both:
- At the edge: country/city/timezone-based quick decisions. Routing, redirect, geo-restrict.
- At origin: complex logic, database access, full personalization.
The edge handles the “fast and simple”; origin handles the “complex and stateful.” For more, see CDN vs edge computing.
TL;DR
- Cloudflare Workers — Best built-in geo data (country, city, ASN, timezone, coords).
- Vercel Edge Functions — Country, city, region; richer signals via API.
- AWS Lambda@Edge — Country, city; combine with API for more.
- Patterns: geo-redirect, country-block, currency-localize, fraud-aware routing.
- For richer data (ASN type, VPN detection), call Ip2Geo from the edge function.
- Cache geo lookups in edge KV stores.
- Cost is modest at most scales (~$500/M requests for compute).
- Combine edge + origin for fast simple decisions + complex stateful logic.
Edge geo processing is one of the highest-leverage uses of edge computing. The data is right there (in the request, from the edge platform); the decisions are fast; the implications are global. Combined with Ip2Geo for richer signals, you get a complete IP-intelligence layer at the edge. For the broader edge concepts, see CDN vs edge computing; for specific personalization patterns, geo personalization.