CDN and caching: offloading the origin without serving the wrong thing
A CDN is a cache with a copy of your site in it. Configured well it removes most of the load from the origin; configured carelessly it serves one visitor's page to another, and the failure is invisible until someone reports it.
Caching is a correctness problem before it is a performance one
The reason to put a CDN in front of a site is to stop the origin answering requests it has already answered. The reason sites get into trouble with one is that the same mechanism will happily cache a page that was specific to a visitor. Cache-key design decides which requests are treated as identical, and getting it wrong is not a slow site — it is the wrong content, served confidently, from a location you cannot easily inspect.
- Most requests still reach the origin despite having a CDN
- A low cache hit ratio and nobody knows which requests are missing
- Editors publish and see the old page for an unpredictable period
- Logged-in users occasionally see a signed-out or another user's view
- Invalidation is a full purge because nobody can target the right objects
- Static assets are cached for a day and changed by deploying the same filename
- The CDN was added and the measured origin load barely moved
- Personalised or geo-specific content is being served from a shared cache
The people who usually bring us this problem
A site with a CDN and a low hit ratio
It is configured, requests still reach the origin, and the reason has not been established.
A site about to add one
You want the cache-key and invalidation decisions made deliberately rather than discovered from a support ticket.
Someone whose content is going stale or leaking
Publishing does not propagate, or a personalised view has been served to the wrong visitor.
What this costs while it goes unfixed
Engineering faults are rarely confined to the engineering layer. These are the commercial consequences we see most often.
The cache key is the whole design
It decides which requests are considered the same, and everything else follows from it. Include too little and different content is served from one entry; include too much and every visitor gets their own, which is a CDN that does nothing while appearing to work. Neither failure announces itself.
A CDN can make a site slower
Every miss is a request that travels to the edge, then to the origin, then back through the edge. If the hit ratio is low — because the key is too specific, or the content is uncacheable — the CDN adds latency to the majority of requests rather than removing it, and the measurement looks like the CDN being slow.
Invalidation has to be targeted or it is expensive
A full purge after every publish is the common answer and it is a poor one: it empties the cache the CDN exists to fill, and the next requests all miss. Invalidation that reaches the right objects requires the site to know what a change affects, which is a design decision rather than a button.
The failure mode is silent and the diagnosis is remote
A cache serving a signed-in view to a signed-out visitor produces no error, no log on the origin and no local reproduction. It is diagnosed from response headers, from what the edge decided, and from the cache key — which is why the design is worth getting right before it happens rather than after.
Capabilities
Each of these is work we carry out, not an area we advise on.
What is cacheable, decided per route class
Static assets, public pages, pages with a shared but varying view, and pages that are specific to a visitor — each classified, with the caching decision made against what the page actually contains rather than against what it looks like.
Cache-key design
Which request properties form the identity of a cached response: path, query parameters, headers, cookies, and how much of each. This is the central decision, and the page describes the reasoning rather than a setting, because the right answer depends on the site.
Invalidation strategy
How a publish or a change reaches the copies already served. Targeted invalidation by path, by tag or by surrogate key where the platform supports it, cache-busting by content hash for assets, and a full purge only where nothing narrower is possible.
Origin offload measurement
What proportion of requests are answered at the edge, what remains, and which requests account for the misses. The hit ratio as a single number hides the answer; the breakdown by route class is where the fix is.
Personalisation and session handling
Where a page varies by visitor, making that explicit — bypass the cache, vary on a safe key, or move the varying part to a request the page makes after load. The last is frequently the right answer and it is a design change rather than a configuration one.
Asset delivery
Immutable caching for content-hashed assets, correct revalidation for anything that cannot be hashed, compression, and the cache-control policy that makes a deploy atomic rather than a window where old and new are both live.
Edge behaviour beyond caching
Redirects, header manipulation, security headers and origin protection applied at the edge where that is the right layer for them — and left at the origin where putting them at the edge would make them harder to reason about.
Verification of what is actually served
Response headers, cache status and the returned body checked from outside the origin, because the cache is a remote system and its behaviour cannot be inferred from the site's own configuration.
Engineering methodology
The sequence is deliberate. The order is usually what determines whether the work holds or has to be repeated.
Classify every route before configuring anything
What each page type contains and whether that differs by visitor. The cache-key decision depends entirely on this, and starting from the configuration rather than the content is how a shared cache ends up serving a private view.
Design the key from the content, not from the platform
Decide what genuinely distinguishes two responses, then express it. A default key is a guess about a site nobody has classified, and it is right for static assets and unreliable for anything dynamic.
Measure the breakdown, not the ratio
Hit ratio by route class, by status code and by request type. A single figure of ninety per cent is compatible with a content type being missed entirely, and the breakdown is where that becomes visible.
Make invalidation a property of the content
The site should know what a change affects rather than purging broadly. Where the platform supports surrogate keys or tags, use them; where it does not, decide the narrowest mechanism available and accept its cost explicitly rather than falling back to a full purge by default.
Treat personalisation as a design question
A page that varies per visitor is not a caching problem to be configured around. Moving the varying element into a request made after the page loads is usually better than either bypassing the cache or varying the key, and it is a change to the page rather than to the CDN.
Verify from the outside
Request the site as a client would, from more than one location, and read what comes back: cache status, age, the key that was used. The origin's configuration describes intent; the response describes what happened.
What an engagement produces
Documentation is a deliverable, not an afterthought. On most of these engagements a large part of the value is a defect report precise enough for another team to act on.
Assessment
- Every route class, with what it contains and whether it varies by visitor
- The current cache key and what it does and does not distinguish
- Hit ratio broken down by route class, status and request type
- What remains reaching the origin, and why
- Current invalidation behaviour, and what it costs
- Anything being served from a shared cache that should not be
Configuration
- Cache-key design expressed per route class
- Cache-control and expiry policy per class, with the reasoning
- Invalidation strategy, targeted where the platform allows it
- Immutable asset caching with content-hashed filenames
- Personalised routes made explicit rather than left to a default
- Edge behaviour limited to what belongs at the edge
Verification
- What is served, checked from outside the origin and from more than one location
- Hit ratio re-measured by class, before and after
- Origin load measured before and after
- Invalidation verified by publishing and observing propagation
- The remaining misses, and what each one is
Architecture and technology
What decides whether a response is cacheable
- Whether the content differs by visitor, by location or by anything else
- Whether the response is the same for every visitor with the same key
- How long it remains correct, and what event makes it wrong
- Whether the request carries cookies or headers that change the answer
- Whether the page is assembled from parts with different lifetimes
- Whether the origin can express what a change affects
Why a CDN makes a site slower
- A cache key so specific that every request is a miss
- Content marked uncacheable because one element on the page is personalised
- Full purges on every publish, emptying the cache repeatedly
- Assets revalidated on every request because filenames are not hashed
- Redirect chains resolved at the edge on every request
- An edge location far from the origin serving a low-traffic region
If this is not quite your problem
These overlap at the edges. Sending you to the right page is more useful than having you work it out.
The origin is the constraint
Serving-path design, capacity and configuration underneath the CDN.
Server managementThe site is slow for reasons above the cache
Application and template performance rather than delivery.
Website performanceSpeed is a search problem here
Field performance as it affects crawling, indexing and ranking.
Core Web Vitals optimisationThe platform needs its own performance work
WordPress performance where caching interacts with the application.
WordPress speed optimisationFrequently asked
Do you have CDN work you can point to?
No, and we will not dress a platform engagement up as one. Our published work is forum and platform engineering in which caching and delivery were part of the engagement. What this page can demonstrate is the mechanism: how a cache key is designed from what a page actually contains, why a full purge on publish is a poor answer, and the specific ways a CDN makes a site slower. That is content a reader can evaluate directly, and it is more useful than a logo would be.
How much will this reduce our origin load?
It depends on how much of the site is cacheable, which is what the classification establishes before anything is configured. A site that is almost entirely public pages can be served mostly from the edge; a site where most pages vary by visitor cannot, and no configuration changes that — it is a property of what the pages contain. The assessment measures the current breakdown first, so the answer is derived from your site rather than offered in advance as a figure.
Why does our site go stale after publishing?
Usually because invalidation is either too broad or too narrow. Too broad — a full purge — means everything is cleared and the cache refills from scratch, so the effect is a period of origin load rather than staleness. Too narrow, or missing entirely, means the specific objects a publish affected are not invalidated and the old version is served until it expires. Which one this is shows up immediately in the response headers, and the fix is making the site express what a change affects rather than relying on a blanket purge.
Is it safe to cache pages for logged-in users?
Not the page as a whole, unless the cache key distinguishes them — and varying on a session cookie gives every visitor their own entry, which is a CDN that does nothing. The better answer is usually to identify what actually varies, serve the shared part from the cache and fetch the varying part after the page loads. That is a change to the page rather than to the CDN, and it is why the classification step comes first: the question is what the page contains, not what the CDN can be told.
Do you work with any particular CDN?
The concepts are the same across providers — cache keys, TTLs, invalidation mechanisms, header handling — and the differences are in what each one lets you express, particularly around targeted invalidation and edge compute. Which provider is in place is established during the assessment, and where the configuration is limited by the provider that is stated as a finding with its consequence rather than worked around silently.
Related capabilities and work
Bring us the problem you have not been able to fix
Describe what is happening rather than what you think the cause is. If we are not the right people for it, we will say so.