August 27, 2026·7 min read

Let the edge do the scaling so the origin can stay small

A network of sites sounds like it needs a big, muscular backend. It doesn't. Put a cache in front, keep the origin one small, well-understood thing, and let the edge absorb the traffic you were about to over-engineer for.

By Andrew Pyle

The instinct when you're about to serve a lot of traffic is to make the server bigger. More workers, more replicas, more of the muscular backend infrastructure that scaling stories are usually about. I've come to think that instinct is backwards for the kind of thing I build, which is mostly read-heavy content served to a lot of people who all want the same pages.

For that shape of problem, the leverage isn't in the origin at all. It's in front of it. Put a good cache at the edge, design so most requests never reach your server, and the origin gets to stay small, simple, and boring — which is exactly what you want the thing you operate alone at 2am to be. My whole network runs this way: a single origin droplet behind Cloudflare, where the edge does the scaling and the part I actually maintain stays deliberately unimpressive.

01Never reach you

Most requests should never reach you

The single most important number in a read-heavy system is the fraction of requests your origin never sees. If a thousand people request the same page and your server renders it a thousand times, you've signed up to scale the origin to the size of your audience. If the edge serves 950 of those from cache and only 50 reach you, you've decoupled your infrastructure cost from your traffic — and decoupling those two is the whole game for a small operation.

So the first design question isn't "how big does the server need to be," it's "how much of this can be cached at the edge, and for how long?" Content that's the same for everyone and changes slowly is nearly free to serve at any scale, because the edge does the serving. The origin's job shrinks to producing the canonical version occasionally, not answering every visitor. That reframing is what turns a scaling problem into a caching problem, and caching problems are much cheaper to have.

Your origin should cost what your content costs, not what your traffic costs. The edge is how you break the link between the two.

02Small is legible

A small origin is a comprehensible origin

The under-appreciated payoff of edge-first isn't just cost, it's comprehensibility. When the edge absorbs the load, the origin doesn't have to be a horizontally-scaled, load-balanced, autoscaling cluster with all the operational surface area that implies. It can be one server running one well-understood stack that I can hold entirely in my head. When something breaks, there's one place to look, not a fleet to reason about. For a one-person operation, a system you can fully understand is worth more than a system that can theoretically scale to the moon.

This is a deliberate trade. I'm choosing a small, single, understandable origin and accepting its limits, because those limits almost never bind — the edge sees to that — and the simplicity pays out every single day in one less thing that can go mysteriously wrong. The complexity I didn't build is complexity I don't have to operate. On that one box lives everything: nginx terminating the requests, a Django app that is the system of record, a small read API in front of it, and the static build of the sites. It is not a small amount of software, but it is a small amount of infrastructure, and the difference between those two is the whole point.

03Design for cache

Design for the cache, not around it

Edge caching only works if you build for it on purpose. That means being honest about what's actually the same for everyone — and it usually is far more than you'd assume — and structuring pages so the cacheable, shared parts aren't contaminated by per-visitor dynamic bits that force everything to render fresh. One personalized fragment carelessly inlined into an otherwise-static page can quietly make the whole page uncacheable, and you'll never notice until your origin is inexplicably busy.

The other half is having a clean way to invalidate. Content that changes slowly still changes, and when it does you need to be able to purge the edge deliberately so the world sees the new version promptly. So a deploy doesn't just ship code; it tells the edge to drop the stale copies. Cache-first isn't cache-and-forget — it's cache aggressively, and own the moment you invalidate. Get both halves right and the edge is a superpower; get only the first and you'll be debugging why nobody sees your update.

04Deploy purges edge

The deploy is where the edge gets told

The invalidation half is not a nice-to-have I bolted on later — it's the last real step of every production deploy. After the code is installed, the services are reloaded, and the health checks have come back green, the pipeline reaches out to Cloudflare and purges the cache so the edge stops serving yesterday's copies. The deploy that ships the change is the same deploy that clears the stale version of it, so there is never a window where new code is live but the old page is still cached in front of it.

In my case the purge is blunt on purpose: the deploy tells Cloudflare to drop everything, rather than trying to enumerate exactly which URLs changed. For a network this size a full purge costs almost nothing — the edge simply refills from the origin over the next few requests — and a blunt purge that always works beats a clever selective one that occasionally misses the one page you actually edited. Being surgical about invalidation is a great way to ship an update that half the world can't see.

# last step of the deploy: drop the edge's stale copies
curl -s -X POST \
  "https://api.cloudflare.com/client/v4/zones/$ZONE/purge_cache" \
  -H "X-Auth-Email: $CF_EMAIL" -H "X-Auth-Key: $CF_KEY" \
  --data '{"purge_everything":true}'

The one nuance is that the purge is deliberately non-fatal. If Cloudflare's API has a bad moment, the deploy logs a warning and finishes anyway, because a purge hiccup should not fail an otherwise-good deploy — the worst case is a few minutes of stale cache that expires on its own, not a broken release. That is the right severity for the step: important enough to run on every deploy, not important enough to hold a good build hostage. The critical things fail loud; the recoverable things are allowed to hiccup.

05TTL per content

What I let cache, and for how long

Not everything gets the same lifetime, and choosing the TTL per kind of content is where the discipline actually lives. The prerendered and static pages — the essays, the project pages, the marketing routes, the stuff that only changes when I deploy — carry a full day of cache. They're the same for every visitor and they change on my schedule, not the visitor's, so a long lifetime is free correctness: nobody sees a stale version, because the deploy purges the edge the moment I do change them. Long TTL plus deliberate invalidation is the combination that makes aggressive caching safe.

The exception proves the rule. The one genuinely live thing on the homepage is the build-time activity stat block, and it's served as a small JSON file with a five-minute cache instead of a day. That short lifetime is a considered choice, not a default: it's the one number allowed to be fresher than the deploy, so I gave it a TTL that lets it update without a release while still shielding the origin from a request per pageview. Everything else earns its long cache by being honestly static; the thing that isn't static gets a short leash instead of poisoning the caching story for the whole page.

06Contained blast radius

One shared blast radius, contained at the edge

There's a risk to running a whole network off one small origin, and it's worth naming: a shared origin is a shared blast radius. If the one server has a bad day, every site behind it has a bad day at once. That would be frightening if the edge weren't sitting in front of it. Because the edge is holding cached copies of the important pages, an origin hiccup doesn't immediately become an outage — the world keeps seeing the cached version while I fix the one thing that broke.

So the edge isn't only a performance tool; it's the thing that makes a small shared origin survivable. It absorbs the traffic on a good day and buffers the failure on a bad one. That combination — one simple origin I can fully understand, fronted by an edge that both scales it and shields it — is what lets one person operate infrastructure that, from the outside, looks like it must have a team behind it. The trick is that the muscle is at the edge, and the part I actually maintain is kept deliberately, stubbornly small.