The pitch for edge compute is simple and true: run the code near the user, cut the round trip. The part that gets left out is that most requests are not waiting on the code. They are waiting on the database, and the database is in Zurich whether you like it or not.
The arithmetic#
A user in Geneva hitting a Zurich database. Function in Zurich: one short hop to the data. Function at the edge in Geneva: the request arrives faster and then makes a long hop for every query it needs.
| Setup | User → fn | fn → db | Total (3 queries) |
|---|---|---|---|
| Function next to the data | ~24ms | ~2ms | ~30ms |
| Function at the edge | ~4ms | ~24ms | ~76ms |
What we do run at the edge#
- Routing decisions: redirects, locale detection, A/B assignment. No data access, and they run before the cache.
- Cached-and-personalised responses: where the payload is static and only a header or a fragment varies.
- Bot and abuse checks: cheapest possible rejection, as far from the origin as possible.
What we keep on Node#
Everything that reads or writes the database, everything that talks to a payment provider, and everything that wants a library written for Node. Which, in a normal product, is most of it.
The part nobody puts on the slide#
An edge runtime is a different runtime, a second set of moving parts, with everything that costs. Your dependencies may or may not run in it, the failure mode is usually at deploy time, and debugging a library that assumed Node APIs exist is not a good use of a Tuesday. That cost is real and it is paid by whoever is on call, not by whoever chose the runtime.