A CDN in front of your origin does nothing on its own. Cache hit ratio is the number that matters, and it is decided almost entirely by headers you control. Here is the reference for getting it from mediocre to boring.
Two policies cover most assets:
Cache-Control: public, max-age=31536000, immutable. The filename changes when the content does, so it can be cached forever, and immutable stops browsers revalidating on reload.Cache-Control: public, max-age=0, s-maxage=60, stale-while-revalidate=86400. Browsers always revalidate, the CDN serves from cache for a minute, and for a day after that it serves stale content instantly while refreshing in the background. That last directive is what removes latency spikes after a cache expiry.stale-if-error=86400 is the companion worth adding: if the origin returns a 5xx, the CDN keeps serving the last good copy instead of passing the error through.
Every varying element multiplies your cached objects and divides your hit ratio. The usual culprits: tracking query parameters (utm_*, fbclid) that change nothing about the response, Vary: User-Agent which effectively disables caching, and Set-Cookie on a static asset response, which most CDNs treat as an instruction not to cache at all. Normalise or strip tracking parameters at the edge, keep Vary to Accept-Encoding and, where you negotiate images, Accept.
Purging one URL at a time does not scale past a handful of pages. Tag responses at the origin — Surrogate-Key on Fastly, Cache-Tag on Cloudflare — with the entity IDs they depend on, then purge every page touching a product with a single tag purge when that product changes. Design the tags when you build the pages; retrofitting them means re-deriving dependencies you no longer remember.
Brotli beats gzip on text at every level, but the cost curve is steep. Pre-compress static assets at build time with maximum effort (brotli -q 11) and serve those files directly; compress dynamic responses on the fly at a middling level, around 4 or 5, where the extra CPU stops paying for itself. Do not compress already-compressed formats — images, video, woff2 — you spend CPU to add bytes.
Without an origin shield, every edge PoP misses independently and your origin sees a request per region. With shielding, one designated PoP fetches and fans out to the rest. On a site with global traffic this is often the single biggest reduction in origin load, and it costs a configuration toggle.
Read the cache status header on real responses — cf-cache-status, x-cache, or the equivalent — and count HIT, MISS, EXPIRED and REVALIDATED separately. A high overall ratio hiding a 40% miss rate on HTML is a different problem from an even spread. For static assets, anything below 95% means your cache key is wrong. For HTML, 60-80% is a realistic target once s-maxage and stale-while-revalidate are in place.
Enable HTTP/3 for lossy mobile networks, where head-of-line blocking hurts most. Use 103 Early Hints with Link: </app.css>; rel=preload; as=style so the browser starts fetching critical assets while your origin is still thinking. And check TLS session resumption is on — a full handshake on every connection is latency you are paying for nothing.
Free tools, guides, and resources across the SPUNK13 network.
Visit spunk.bet400+ Free Tools