Your origin is in one region and readers are worldwide. What do you cache, and what happens the moment you must invalidate it?
CDN caching for global reads works when cacheable bytes are separated from personalised fragments. Use content-addressed assets, tag-based purges for pages that must change, and plan for purge storms because invalidation sends cold traffic back to the one origin region. It also connects http caching to the point an interviewer is testing.
What the interviewer is scoring
- Whether the benefit of an edge cache is stated as removing round trips rather than only reducing origin load
- Does the candidate reason about the cache key and what varying on a header multiplies it by
- That renaming is offered as the preferred alternative to invalidating, with the class of content it applies to named
- Whether a purge is treated as a distributed write that can partially succeed, and the reader-visible consequence stated
- Can they quantify the origin load that a short lifetime creates, and compare it with the cost of running purges
Answer
Short answer
Cache the shared shell and static assets globally, keep personal data out of the cached object, use immutable asset URLs, and treat purges as origin load events that need protection.
The distance is the problem, and it is not about CPU
Put the geography into numbers first, because it decides what caching is for. Light in fibre travels at roughly 200,000 kilometres a second. Dublin to Sydney is about 17,000 kilometres on a great circle, so an ideal round trip is 170 milliseconds, and real routes are not great circles - 250 milliseconds and upwards is what you measure.
Now count the round trips before a Sydney reader sees any HTML. A TCP handshake, then a TLS handshake, then the request itself. Even at two round trips before the first byte, that is 500 milliseconds spent on nothing but distance, before your origin has read a single row. Your server could answer in one millisecond and the reader would not notice the difference.
That is why an edge cache is not primarily an origin-offload device. It is a latency device. Terminating the connection 20 milliseconds from the reader removes the handshakes from the long path, and the cached body removes the last round trip too. The origin savings are real and secondary.
What is cacheable is decided by the cache key
The rule is simple to state: a response is cacheable at the edge if its bytes do not depend on who asked. The difficulty is that most pages are 95 per cent identical for everyone and 5 per cent personalised. That 5 per cent poisons the whole document.
So the design move is to split the page rather than to give up on caching it. The article body, the navigation, the images and the scripts go in one cacheable document. The logged-in name, the basket count and anything user-specific are fetched separately by the client, or composed at the edge from a cached shell plus an uncached fragment. Which of those two you pick is a rendering decision. What matters is that the personalisation is separated out rather than embedded.
Then look at the cache key, which is where hit rates are quietly destroyed. Every dimension you vary on multiplies the number of copies of the same page. Vary on encoding at three values, times a device class at two, times twelve locales, is 72 stored variants of one URL. Your origin now serves 72 cold fetches for that page instead of one, and each variant's copy expires independently, so a page with modest traffic may never accumulate enough requests to be warm anywhere.
Normalise before you key. Collapse device detection to two buckets rather than a user-agent string. Resolve locale to a path segment so it is visible in the URL rather than hidden in a header. Strip query parameters that came from campaign tracking, because ?utm_source=x produces a distinct key for a byte-identical page and marketing will generate hundreds of them.
The content you never have to invalidate
Split your content in two by how it is versioned, because one half of the invalidation problem should be designed out rather than solved.
Anything built by your pipeline gets a content-addressed name. A stylesheet becomes main.9f2c1a.css, where the hash is over the bytes. That file is now immutable by construction: a change produces a different name, and the old name keeps serving the old bytes for as long as anyone asks. So you set a lifetime of a year, mark it immutable so a reader's reload does not revalidate it, and you never purge anything. Deployment becomes a matter of publishing new names and pointing the HTML at them.
What is left is the content whose URL is the identity: an article at a permanent path, a product page, the homepage. Those must be mutable. They are what invalidation exists for, and they are a small fraction of your bytes.
A purge is a distributed write and it can half-succeed
Here is the part that separates an answer from a recital. Invalidation is not a local operation. Your content lives in every location that has served it, and a purge has to reach all of them. That makes it a write to tens of independent caches, with its own propagation delay and its own partial-failure mode.
The consequence is concrete. If the purge lands at 38 locations and not at two, then two cities are serving the old article while everyone else has the new one, and nothing in your system knows. A reader emails to complain about a correction you made two hours ago and your own browser shows the corrected copy. The debugging path for that starts with knowing which location served the response, which is why an edge-identifying response header earns its place in production.
sequenceDiagram
participant E as Editor
participant O as Origin
participant C as Purge control plane
participant A as Edge Dublin
participant B as Edge Sydney
E->>O: publish correction
O->>C: purge tag article-4471
C->>A: purge
A-->>C: acknowledged
C--xB: no acknowledgement
Note over B: still serving the old body<br/>only a reader will noticeLook at the unacknowledged branch rather than the happy path. The design question a purge raises is not how to send it, it is how you find out it did not arrive, and the answer has to be an acknowledgement you check rather than a request you fired.
Purging by tag, because you do not know all the URLs
The second half of the invalidation problem is knowing what to purge. An article appears at its own URL, and also on the homepage, three category listings, a feed and a search results page. Purging the article's own URL leaves five stale copies of its headline in circulation.
The workable mechanism is to attach tags to a response as it leaves the origin, naming every entity that contributed to it, and to purge by tag rather than by path. The homepage response carries the tags of the twelve articles it embeds. Correcting one article purges everything tagged with it, wherever it appears, without your application maintaining a reverse index of pages by content.
The alternative people fall back on is purging everything. Be clear about what that costs. Emptying every location's cache means the next request for every page goes to the origin, from every location, at once. That is a self-inflicted version of exactly the traffic pattern the cache exists to prevent, and it arrives at your single origin region across an ocean.
Long lifetimes with purge beats short lifetimes
The tempting simplification is to skip purging and set a 60-second lifetime everywhere, accepting a minute of staleness in exchange for never operating an invalidation system. Cost that out before choosing it.
With 40 locations and 10,000 popular pages, a 60-second lifetime means each location revalidates each page once a minute. That is 40 times 10,000 divided by 60, roughly 6,700 requests a second of pure revalidation, arriving at one origin, forever, whether or not anything changed. Conditional requests make each one cheap, but you are still paying the connection and the round trip across the same ocean you built the cache to avoid.
So the trade is legible: long lifetimes plus tag-based purging costs you an invalidation system to operate and debug, and short lifetimes cost you continuous origin load and a permanent staleness floor. At scale the first wins. That is why every serious content platform runs a purge pipeline rather than a short timer.
Two smaller things make the whole arrangement tolerable. Request coalescing at each location, so a hundred simultaneous misses for the same object become one origin fetch rather than a hundred. And serving the stale copy while a single refresh runs behind it, so a purge or an expiry degrades freshness for a moment instead of degrading latency for everybody.
Design the invalidation before the caching. Content whose URL contains a hash of its bytes never needs purging at all, and everything left over needs a purge you can address by entity, acknowledge per location, and survive without your readers being the ones who tell you it failed.
© 2026 Preptima. Originally published at preptima.com.
Likely follow-ups
- An article is embedded on the homepage, three category pages and a feed. You correct the article. Which URLs need purging, and how does the system know?
- How do you serve a logged-in header on a page whose body you want cached for a day?
- A purge succeeds at 38 of 40 locations. How would you find out, and what do you tell the editor who asked for it?
- Your busiest reader region has one location and it is now the origin's biggest client. What changes in the topology?
Related questions
- What goes into a cache key, and what happens when two requests that should get different responses collide on one?hardAlso on http-caching and cache-keys6 min
- Where do you put the cache, and how big does it need to be?hardAlso on cdn and http-caching6 min
- A two-hour film must start playing within two seconds on a phone on 4G. What has to exist before the play button works?hardAlso on cdn6 min
- Photos are the payload, thumbnails are the traffic, and both must survive losing a disk. Where does each copy live?hardAlso on cdn5 min