The Edge Is Not a CDN: Why Moving Compute Closer Often Makes Things Slower
Caching at the edge moves bytes closer to users. Running code at the edge moves the code away from the data. What that trade costs, and when it genuinely pays.
5 min read
On this page
A team moves its API handlers to the edge, expecting the same win the CDN gave them, and the responses get slower. Not everywhere and not for everything — the static assets are as fast as ever, and a couple of endpoints improved. But the pages that matter, the ones that read the user's data, are worse from further away.
The result is confusing only because of the word. Both things are called "the edge", and they do opposite things to the distance between compute and state.
Two different problems
A CDN moves bytes closer to users. The bytes are a copy, the copy is complete, and once it's in the nearest location the origin is out of the request path entirely. That's why it works so reliably: the data went with the compute.
Edge compute moves code closer to users. The data stayed where it was. You have shortened the leg between the user and the code, and lengthened the leg between the code and the database — and for most application handlers, the second leg is traversed several times.
The arithmetic is the whole argument
Call the round trip between an edge location and your database's region R, and the round trip between the user and either location roughly comparable in scale.
Run the handler in the database's region: the user pays one long trip, and each query costs almost nothing because the database is next door. Three sequential queries, one long trip.
Run the same handler at the edge: the user's trip is short, and each query now costs R. Three sequential queries, three long trips.
For a handler with a single query, it's close to a wash. For a chatty handler — and most handlers are chattier than their authors think, once you count the session lookup, the permission check, the feature flags and the actual query — edge execution multiplies the expensive leg by the number of round trips. The classical fix for chattiness is to move the logic next to the data. Edge compute is that advice run backwards.
Connections make it worse rather than better. An ephemeral instance in many locations, each establishing connections to one database, is a poor fit for a connection-limited server, and the pooler you add to fix it sits in the database's region — so the first hop is long anyway.
What genuinely gets faster
The pattern in every real win is the same: the decision needs no state from the origin, because the state is either in the request itself or replicated to every location.
Verifying a signed token against a public key you already hold. Redirects, rewrites and canonical-URL logic. Assigning a user to an experiment bucket and setting the cookie. Locale and geography routing. Bot filtering and abuse rejection, where the point is precisely to spend nothing at the origin. Normalising or validating a request before it travels. Assembling a personalised shell around cached content. Serving from a key-value store that the platform replicates everywhere.
Each of these removes a full origin round trip rather than adding several. That's the test worth applying to any candidate: does moving this to the edge eliminate a trip to the origin, or does it introduce trips that used to be local?
Cold starts and the second runtime
Edge platforms start code quickly, but the traffic maths works against you. The same request volume is now divided across far more locations, so each location sees a thinner stream and is correspondingly more likely to be starting cold. Popular locations stay warm; the long tail of locations doesn't, and those are exactly the users you moved compute closer to help.
The runtime constraints are the part that outlasts the latency debate. Edge runtimes buy their fast start by being smaller: restricted or absent raw sockets, no arbitrary native dependencies, limits on CPU time and memory per request, bounded response durations, and a standard library that differs from the one your server code uses.
The real cost isn't that some libraries don't work. It's that your edge code and your origin code stop being the same code — different capabilities, different failure behaviour, two sets of bugs, and a class of problem that only reproduces in one of them. That's an ongoing tax, and it's paid whether or not the latency improved.
Data residency is the honest driver
The most defensible reason to run compute in many places has little to do with speed.
If records belonging to users in a jurisdiction must remain in that jurisdiction, you need regional data whether or not you wanted it — and once the data is regional, compute belongs beside each region's copy. The requirement forces the partition; placing the compute is just following it.
This reframes the whole exercise. It isn't a CDN feature, it's sharding by user with a routing layer in front, and it inherits every hard problem sharding has ever had: queries that need to span regions, identifiers that must be globally unique, migrating a user from one region to another, and a control plane that must itself be reachable everywhere while owning data that lives somewhere. Those are the problems worth planning for. Cold starts are not.
Put the compute where the data is
The useful rule survives the marketing. Cache aggressively at the edge, because copying bytes closer is an unambiguous win. Keep application logic beside its data, because round trips between code and state dominate everything else. Move to the edge only the work that needs no origin state — and if you're moving compute for latency rather than for residency, be prepared to move the data with it.
Otherwise you've optimised the one leg of the journey that was already short.