
Optimizing Vercel for Lower Carbon Emissions: A Developer's Guide

Michael
October 20, 2025
TL;DR
- Default problem: Vercel functions run in Washington D.C. (400g CO₂/kWh, 8% renewables) by default
- Quick fix: Switch to Stockholm (20g CO₂/kWh, 60% renewables) or Portland (194g CO₂/kWh, 66% renewables) via vercel.json
- Impact: 95% lower emissions, often better latency for EU users, GDPR compliance benefits
- Trade-off: Consider data source co-location to avoid extra roundtrips
- Bonus: Proper caching eliminates function execution entirely (zero additional emissions from compute)
Introduction
We love building with Next.js and Vercel's developer experience - seamless CI/CD, preview deployments, zero-config hosting. After signing the Green Software Manifesto and joining the Bundesverband Green Software as a B Corp, we asked: Can we run our workloads on cleaner grids without hurting performance or costs?
Short answer: Yes. Choosing the right regions made our apps greener, often faster, and sometimes cheaper. Here's the playbook.
The Problem: Default Configuration Runs on High-Carbon Grids
By default, all Vercel Node.js functions execute in Washington D.C. (iad1), which runs on one of the dirtiest electricity grids in their network:
- 400g CO₂/kWh
- 8% renewable energy
- 🙀 Primarily coal, gas, and nuclear
Electricity mix: Washington DC (2024, electritymaps.com)

Every API route, server-side render, and database query runs there unless you configure otherwise. This is especially important for non-US based user bases. As a European company with 80% of visits from Germany, this means serverless functions execute in the US by default, which results in a 12,000 km roundtrip per function call.

Fortunately, Vercel provides options to change the default region(s).
Understanding Deciphering Vercel's Architecture
Vercel's terminology can be confusing. Let's clarify what Edge POPs and Function regions actually mean:

Source: https://vercel.com/docs/cdn
POP vs Edge
The 126 POPs (Points of Presence) are actually what I would describe as edge endpoints as they are globally distributed, the first touchpoint of a request and thus closest to the user.
The 19 Edge Regions are the only compute-capable regions "where your code runs close to your data" which is why I propose calling them function regions rather than edge regions.
See region list and runtimes for more background.
This means...
POPs
- (CDN) Cache: Static assets, cached responses
- Edge functions: Can execute edge functions with a limited runtime (similar to Cloudflare workers)
Edge Function Region
- Serverless functions: This is where serverless functions (Node.js, Go, Python, Ruby) will be executed
- Data Cache: HTTP calls made from within your function are being cached at that exact region
Caches

Edge Cache (lives in POP region)
Requests arrive at the closest POP (Edge) and this is where the cached data lives:
Vercel's Cache is used for caching entire static assets at the edge, such as images, fonts, and JavaScript bundles.
Vercel clarifies that "Static files are automatically cached at the edge on Vercel's CDN for the lifetime of the deployment after the first request.", which is great!
We won't make it too easy, so there are three more terms that are related to the edge cache:
- Fast Origin Transfer: The data transfer between Vercel's CDN (POP) to Vercel Compute (Function region)
- Fast Data Transfer: The data transfer between Vercel's CDN (POP) and your sites' end users (Browser)
- ISR: Incremental Static Regeneration: (ISR) allows you to create or update content on your site without redeploying, which will be cached at edge (POP)
You can inspect the response headers to see if a request came from cache and which POP was in charge of delivery:
Header | Value | Description |
---|---|---|
x-vercel-cache | HIT | Indicates cache hit |
x-vercel-id | fra1::fm62r-1758702865455-d92e4103debc | Shows POP location |
In this case "fra1" is Frankfurt, Germany. See region list
Data Cache (lives in function region)
The data cache is located at the function region you defined. So all fetch calls for instance are being cached at the same location as your function. Each region has its own cache though. A cached fetch call in Frankfurt won't be available in Stockholm.
You can see for yourself on Vercel: Observability > Data Cache
Functions / Compute - The Core of Carbon Optimization
Now we come to the heart of this guide: where your compute actually runs. This is where you have the most control over your carbon footprint and where regional choices make the biggest difference.

Source: https://vercel.com/docs/cdn
Vercel has three types of compute, each with different carbon implications:
The routing flow:
- Request hits nearest PoP (out of 126 globally)
- Static content served from cache if available
- Edge Functions run at the PoP
- Node.js Functions route to your configured region (function region)
☝️ Vercel states: "We recommend migrating from edge to Node.js for improved performance and reliability." (https://vercel.com/docs/functions/runtimes)
Steps 3 & 4 are what you control. With Vercel's recommendation to migrate from Edge to Node.js runtime, the regional optimization becomes even more important.
Debugging request flow:
To see how your requests flow through the Vercel Edge Network, you can check the x-vercel-id header in your HTTP responses. This header reveals the edge region that handled the request and the region where any functions (Edge or serverless) were executed.

You can also check in Vercel Dashboard: Observability → Data Cache and Regions to verify your setup.
💡 I highly recommend reading this blog post series from Vercel:
🗺️ Region Analysis: Carbon Intensity Data
We analyzed EU and US Vercel compute regions using 2024 annual average data from ElectricityMaps (accessed September 2025).
EU Regions (2024 Annual Average)
AWS Region | Location | CO₂ (g/kWh) | Low-Carbon % | Renewable % |
---|---|---|---|---|
eu-north-1 (arn1) | Stockholm, Sweden | 20 | 100% | 60% |
eu-west-3 (cdg1) | Paris, France | 33 | 96% | 29% |
eu-west-2 (lhr1) | London, England | 175 | 71% | 51% |
eu-west-1 (dub1) | Dublin, Ireland | 309 | 46% | 40% |
eu-central-1 (fra1) | Frankfurt, Germany | 334 | 66% | 61% |
US Regions (2024 Annual Average)
AWS Region | Location | CO₂ (g/kWh) | Low-Carbon % | Renewable % |
---|---|---|---|---|
us-west-2 (pdx1) | Portland, USA | 194 | 70% | 66% |
us-west-1 (sfo1) | San Francisco, USA | 231 | 62% | 52% |
us-east-1 (iad1) | Washington, D.C., USA | 400 | 40% | 8% |
us-east-2 (cle1) | Cleveland, Ohio, USA | 400 | 40% | 8% |
Looking at the data you can see that low carbon % and renewable % are not aligned in many cases. This is due to the extensive use of ☢️ nuclear energy in some countries.
Depending on your position in regards to nuclear energy and your GDPR needs, you can pick the regions that suit you the most.
Implementation: How to Switch Regions
1. Functions
See Vercel Functions - Configuring Regions for the official documentation.
Method 1: Project-wide Configuration (Vercel.json)
Method 2: CLI command
Method 3: Dashboard Configuration

Project Settings → Functions → Function Regions → Select regions
2. Edge functions
Per-Route Configuration
Note: Per-route preferredRegion is limited to Edge Functions. See Vercel Edge Runtime - Regions
The Critical Co-location Caveat
Don't just pick the cleanest region—consider your data sources and user location
By default, Vercel Functions execute in Washington, D.C., USA (iad1) for all new projects to ensure they are located close to most external data sources, which are hosted on the East Coast of the USA.
While this default makes sense for US-centric applications, it may not be optimal for companies with different user distributions or data residency requirements.
The distance between your users, function regions, and data sources significantly impacts both carbon emissions and latency.
A quick reference guide for calculating the impact of colocation:
Latency
~5-7ms per 1,000 km
Carbon
~0.05 Wh/GB/km (0.00005 kWh/GB/km) for network transmission in fiber networks
Rule of thumb
Real-world fiber paths are typically 1.5× great-circle distance due to routing

In order to pick the right region(s), you need to answer two questions:
1. Where are your users located?
Look at your analytics and try to find regions that are as close as possible, as green as possible, and fully compliant with your legal requirements (GDPR → EU-only).
Example: If most of your traffic is from Germany, the default routing to Washington means 12,000km roundtrip per function call and a possible GDPR violation.
You can use Vercel's own Observability Notebooks to lookup the POP distribution.

2. Where are your data sources located?
Your function might call various data sources in order to gain the data it needs for rendering/responding. Make sure those sources are close to your function location(s).
Example: If most of your traffic is from Germany, your function is set to run in Washington and database is defined to run in Frankfurt, you're adding another 12,000 km roundtrip on top.
API endpoints
API endpoints like the GraphQL endpoint of your favorite headless CMS (ours is DatoCMS) will be called from the function. Try to find out where their servers are located. In most cases those APIs will be globally distributed and cached, so you might only find the edge node that your fetch call reaches. That's fine, because in that case you don't have to care about it yourself. Additionally, most fetch calls are cached by Vercel in Data cache in the same region your function is executed.
You can see the external APIs and the cache status in the Vercel logs.

Databases
Modern cloud databases provide you the option to define the region and/or define read replicas in multiple regions. This is especially important when it comes to GDPR and compliance.
Let's look at three famous examples from the Vercel universe:
Vercel vs Database Provider Regional Coverage Matrix (September 2025)
Vercel Region | Reference Location | Neon: PostgreSQL | Supabase: PostgreSQL | Upstash: Redis |
---|---|---|---|---|
arn1 | Stockholm, Sweden | ❌ | ✅ eu-north-1 | ❌ |
bom1 | Mumbai, India | ❌ | ✅ ap-south-1 | ✅ ap-south-1 |
cdg1 | Paris, France | ❌ | ✅ eu-west-3 | ❌ |
cle1 | Cleveland, USA | ❌ | ❌ | ⚪ us-east-2 |
cpt1 | Cape Town, South Africa | ❌ | ❌ | ❌ |
dub1 | Dublin, Ireland | ❌ | ✅ eu-west-1 | ✅ eu-west-1 |
dxb1 | Dubai, UAE | ❌ | ❌ | ❌ |
fra1 | Frankfurt, Germany | ✅ eu-central-1 + azure-gwc | ✅ eu-central-1 | ✅ eu-central-1 |
gru1 | São Paulo, Brazil | ✅ sa-east-1 | ✅ sa-east-1 | ✅ sa-east-1 |
hkg1 | Hong Kong | ❌ | ❌ | ❌ |
hnd1 | Tokyo, Japan | ❌ | ✅ ap-northeast-1 | ✅ ap-northeast-1 |
iad1 | Washington D.C., USA | ✅ us-east-1 + azure-eastus2 | ✅ us-east-1 | ✅ us-east-1 |
icn1 | Seoul, South Korea | ❌ | ✅ ap-northeast-2 | ❌ |
kix1 | Osaka, Japan | ❌ | ❌ | ❌ |
lhr1 | London, UK | ✅ eu-west-2 | ✅ eu-west-2 | ✅ eu-west-2 |
pdx1 | Portland, USA | ✅ us-west-2 | ❌ | ✅ us-west-2 |
sfo1 | San Francisco, USA | ❌ | ✅ us-west-1 | ✅ us-west-1 |
sin1 | Singapore | ✅ ap-southeast-1 | ✅ ap-southeast-1 | ✅ ap-southeast-1 |
syd1 | Sydney, Australia | ✅ ap-southeast-2 | ✅ ap-southeast-2 | ✅ ap-southeast-2 |
- ✅ Direct Regional Match - Provider has a data center in the same or very nearby location
- ⚪ Nearby Region - Provider serves this region from a nearby location (higher latency)
- ❌ No Coverage - Provider does not have presence in this region or nearby
Sources:
Real-World-Example
Consider a German e-commerce site with the default setup (functions in Washington, D.C., database in Frankfurt):
- User request: Berlin → Frankfurt (POP) → Washington, D.C. (~6,550 km)
- Database query: Washington, D.C. → Frankfurt (~6,550 km)
- Database response: Frankfurt → Washington, D.C. (~6,550 km)
- Response to user: Washington, D.C. → Frankfurt (POP) → Berlin (~6,550 km)
Total distance: ~26,000 km over the ocean for a single request that needs database data.
Estimating the Impact (network only):
-
Latency overhead: ~200–260 ms added (vs. ~10–20 ms if everything is in Frankfurt
-
Carbon overhead: ~0.12 g CO₂ per request (≈1 MB crossing the Atlantic; scales linearly)
-
At scale: 10M requests/month ≈ ~14 t CO₂/year from transmission alone (≈~18 t/year at 0.15 g/request)
-
Fixed networks use about 0.05 Wh per GB·km. Assuming ~1 MB total crosses the Atlantic per request (request + DB roundtrip + response), that’s ≈ 0.33 Wh ⇒ ~0.12 g CO₂ per request (at ~360 g CO₂/kWh). Payload scales linearly: a lean ~0.35 MB would be ~0.04–0.05 g; ~1.3 MB ≈ ~0.15 g.
By co-locating functions and data in Frankfurt, you eliminate the transatlantic legs, cutting long-haul latency and carbon by ~85–90% and slashing transmission emissions for dynamic requests.
Important: Cache hits bypass function execution and long-haul transit, so additional network CO₂ is effectively zero regardless of region. Proper Cache-Control headers can dramatically reduce both emissions and latency.
The Broader Context
Vercel's sustainability approach is limited—their Green Energy Policy mostly defers to AWS and Microsoft. We'd love to see them publish per-region sustainability metrics or get listed in the Green Web Directory.
But while we wait for that, optimizing regions is a concrete step developers can take today.
Sources:
Questions or experiences to share? We're always interested in comparing notes on sustainable development practices.
Read also

Julia, 10/14/2025
A beginner's guide to the terminal
Terminal
Guide
Beginner
Development

Lisa, 06/30/2025
“How sustainable is my company?” A first look at the B Impact Assessment
Corporate Social Responsibility
B Corp Zertifizierung
B Impact Assessment
Nachhaliges Wirtschaften
Impact Tools

Michael, 06/12/2025