Route API requests to different backends based on the user's geographic location. Zuplo detects the user's country at the edge and this example maps it to regional backends.
This pattern is useful for:
- Data residency compliance: Keep EU data in Europe, US data in America
- Latency optimization: Route users to the nearest regional backend
- Regional feature rollouts: Test features in specific regions before global release
Prerequisites
- Node.js 18+ installed
- A Zuplo account (only required for deployment). You can sign up for free.
Working with this Example
Locally
Get a local copy using the Zuplo CLI:
Start the development server:
The server starts on http://localhost:9000.
Deploy to Zuplo
Click the Deploy to Zuplo button on this page to deploy directly to your Zuplo account.
How It Works
The geolocation-routing policy runs before each request:
- Reads the user's country from
context.incomingRequestProperties.country(detected from IP at the edge) - Maps the country to a region using
ROUTING_CONFIG(americas, europe, apac, or global) - Sets
context.custom.backendUrlto the regional backend URL - Adds
X-Routed-RegionandX-Detected-Countryheaders to the request
The urlForwardHandler then forwards the request to ${context.custom.backendUrl}.
Region Mapping
| Region | Countries | Environment Variable |
|---|---|---|
| Americas | US, CA, MX | API_URL_AMERICAS |
| Europe | GB, FR, DE, IT, ES, NL, + 20 more | API_URL_EUROPE |
| APAC | JP, KR, AU, NZ, SG, IN, + 7 more | API_URL_APAC |
| Global | All others (fallback) | API_URL_DEFAULT |
All regions default to https://echo.zuplo.io — an echo service that returns your request details as JSON, making it easy to verify routing is working.
Project Structure
API Endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/{path} | Forward GET request to regional backend |
POST | /v1/{path} | Forward POST request to regional backend |
Testing
Note: Real geolocation detection only works when deployed to Zuplo's edge. Locally, use the
X-Test-Countryheader to simulate different locations.
Use the -i flag with curl to see response headers:
You'll see headers showing the routing decision:
Test different regions
The response body from echo.zuplo.io shows your forwarded request details as JSON.
Configuration
To route to real regional backends, set these environment variables:
| Variable | Description | Default |
|---|---|---|
API_URL_AMERICAS | Backend for Americas | https://echo.zuplo.io |
API_URL_EUROPE | Backend for Europe | https://echo.zuplo.io |
API_URL_APAC | Backend for Asia-Pacific | https://echo.zuplo.io |
API_URL_DEFAULT | Fallback for other regions | https://echo.zuplo.io |
Local development: Copy env.example to .env and update the URLs (cp env.example .env).
Deployed projects: Set in the Zuplo Portal under Settings → Environment Variables.
Extending This Example
- Add regions: Add new entries to
ROUTING_CONFIGandgetBackendUrl()inmodules/geolocation-routing.ts - Add authentication: Include
api-key-authin the policy chain beforegeolocation-routing - Add rate limiting: Apply different rate limits per region using
context.custom.region - Combine with A/B testing: Route a percentage of traffic to alternate backends per region
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Always routes to global | Country not in ROUTING_CONFIG | Add country code to the appropriate region |
X-Test-Country header not working | Header not being sent | Verify with curl -v that header appears in request |
| Wrong region in logs | Country mapped incorrectly | Check ROUTING_CONFIG in geolocation-routing.ts |
| Backend URL undefined | Environment variable not set | Defaults to echo.zuplo.io; set env var for real backend |