Edge Functions vs Serverless Containers: Reducing Global API Latency to Under 50ms
Bypassing speed-of-light latency bounds: deploying Edge Functions across global Points of Presence, V8 isolate memory models, and distributed DB read replicas.
By Uttam Thapa · · SaaS
⚡ Executive Summary (TL;DR)
A user in Sydney hitting an API in Virginia pays roughly 240 ms before your code runs a single instruction — that is physics, not slow software.
Edge functions execute in a V8 isolate at the point of presence nearest the user, which removes almost all of it.
But only if the handler does not then call back to a single-region database, which is the mistake that makes most edge
migrations slower than what they replaced.
Figure 1: Execution moves to the user. Whether the data moves with it is the decision that determines the result.
Where the Latency Actually Comes From
When an international request feels slow, engineers reach for profiling. Usually there is nothing to find, because the time was spent before the handler started.
Light in fibre travels at roughly two thirds of c, routing is never a straight line, and TLS costs additional round trips. That budget is fixed by geography.
| User location |
Round trip to a single US-East origin |
Round trip to a nearby edge PoP |
| London | ~95ms | ~12ms |
| Tokyo | ~185ms | ~18ms |
| Sydney | ~240ms | ~22ms |
Those are network figures, not benchmarks of your code, and they compound. A page that makes three sequential API calls multiplies the penalty by three before
any rendering happens.
Edge Functions and Serverless Containers Are Different Products
They are often presented as two points on one spectrum. They are not — they run different runtimes with different capabilities, and picking between them is a
capability question before it is a latency question.
🌐 Edge functions
- • V8 isolate, not a container — cold start measured in single-digit milliseconds
- • Deployed to every PoP automatically
- • Web-standard APIs only:
fetch, Request, Response, Web Crypto
- • No TCP sockets, so no traditional database driver
- • Tight memory and CPU-time ceilings
📦 Serverless containers
- • Full Node.js runtime with the whole npm ecosystem
- • One region, so distant users pay the full round trip
- • Cold starts in the hundreds of milliseconds
- • Persistent connections and native modules work normally
- • Generous memory and execution time
A Vercel Edge Route
The API surface is deliberately small. Anything reaching for Node built-ins will fail at build time rather than at runtime, which is the right trade.
// api/edge-search.ts
export const config = { runtime: 'edge' };
export default async function handler(req: Request) {
// Geo headers are injected at the PoP — free personalisation with no lookup.
const geoCountry = req.headers.get('x-vercel-ip-country') || 'US';
// Cache at the edge so most requests never leave the PoP at all.
const res = await fetch('https://accelerate.prisma-data.net/v1/products', {
headers: { 'Cache-Control': 's-maxage=60, stale-while-revalidate=300' },
});
const data = await res.json();
return new Response(JSON.stringify({ data, geoCountry }), {
headers: { 'Content-Type': 'application/json' },
});
}
The stale-while-revalidate directive is what makes this fast in practice. For the sixty seconds a response is fresh, the PoP answers directly; for
the next five minutes it serves the stale copy immediately and refreshes in the background. Only the first user in each region ever waits.
🚨 The mistake that makes edge slower
Moving a handler to the edge while leaving the database in one region relocates the wait rather than removing it. The user's request now reaches Sydney in
22 ms, and the handler then spends 240 ms querying Virginia — plus a fresh connection handshake, because edge isolates cannot hold a pool. That is a
net regression, and it is the single most common outcome of an edge migration.
The Data Has to Move Too
Edge compute is only as fast as its slowest dependency, so the useful question is not "can this handler run at the edge" but "can this handler answer without
crossing an ocean". Three approaches, in increasing order of effort:
Cache at the PoP
Best for read-heavy, slightly stale-tolerant data — catalogs, marketing pages, public profiles. Cheapest by far.
Global read replicas
Reads served locally, writes forwarded to the primary. You inherit replication lag as a correctness concern.
HTTP data proxy
A connection-pooling proxy that speaks HTTP, so the edge runtime can query without a TCP driver.
What Belongs at the Edge
Edge functions are excellent for work that is small, stateless, and needed on every request: authentication checks on a token you can verify locally, geo-based
routing and redirects, A/B assignment, bot filtering, request rewriting, and personalising cached HTML. All of these read a header, decide something, and return
— never touching your origin.
Keep long-running work, anything needing a transaction, heavy dependencies, and anything requiring native modules in a regional runtime. Splitting along that
line gets you most of the latency win with none of the migration pain.
✅ Key takeaways
- ✓Distance is a fixed cost. No amount of profiling recovers a 240 ms round trip.
- ✓Edge and serverless are different runtimes, not two settings of one. Choose on capability first.
- ✓Move the data or you move the problem. An edge handler querying one region is slower than the original.
- ✓
stale-while-revalidate does the heavy lifting. Only the first user per region should ever wait.
- ✓Put decisions at the edge, work in a region. Auth checks, redirects and rewrites belong close; transactions do not.
Related: deploying full-stack applications covers the configuration side of this, and
scaling PostgreSQL explains why connection pooling is the constraint that decides
whether the edge is available to you at all.
Frequently asked questions
What is the real difference between edge functions and serverless containers?
Edge functions run in a lightweight runtime at many locations with near-zero cold start, but with a restricted API surface. Serverless containers give you the full Node runtime in one region, with cold starts and further distance from most users.
When should you not use edge functions?
When the work needs a persistent database connection, a large dependency tree, or Node APIs the edge runtime does not implement. Being close to the user does not help if every request then crosses the planet to your database.
Does moving to the edge always reduce latency?
No. It reduces network distance for the request, but if the handler makes a round trip to a single-region database you have added a hop rather than removed one. Move the data, or cache at the edge, for the gain to be real.
Home · Projects · Blog · Services · Résumé · Contact