Case studies
Case study: a news site's cache header setup
A high-traffic Turkish sports news site manages caching from its own origin instead of the panel. Four content tiers, four different Cache-Control headers — all verifiable from the outside.
Back to Platform HelpThe live response headers from a real account, and why each one was chosen. The customer isn't named; every header shown here is written so you can verify it on your own site by running the same command.
Four tiers, four different lifetimes
A single cache lifetime doesn't work for a news site: the homepage changes by the minute, the logo doesn't change for years. This account splits content by how fast it changes.
| Content | Header sent by the origin | Why |
|---|---|---|
| Homepage | public, max-age=30, s-maxage=30, stale-while-revalidate=60 |
Breaking news refreshes every 30 seconds; when it expires the visitor shouldn't have to wait — the edge serves the stale copy while it revalidates in the background. |
| Section and listing pages | public, max-age=300, s-maxage=300, stale-while-revalidate=600 |
Category pages don't change as often as the homepage. Five minutes isn't a delay the editorial team would notice, and it cuts the load on the edge considerably. |
| Versioned static file | public, max-age=31536000, s-maxage=31536000, immutable |
The filename carries a version, so its content never changes. immutable stops the browser from revalidating even before max-age expires. |
| Optimized image | max-age=31536000 + public on a separate line |
This line is written by the edge, not the origin — when Image Optimization is on for a rule, the header is regenerated unconditionally. |
Setting up the same layout on your own site
Split content by how fast it changes
Decide which path changes how often before you decide on lifetimes — the lifetime is a consequence of that decision.
- Changes within minutes: homepage, live scores, breaking-news feed
- Changes within hours: category pages, archive listings
- Never changes: CSS, JS, fonts, logo — anything whose filename carries a version
- Personal: logged-in pages, cart, account — these aren't cached and shouldn't be
Send the headers from your origin
Your application or web server sends the header. You don't need to enter a lifetime in the panel — the two approaches don't work together on the same rule.
- s-maxage is for the shared cache (the CDN), max-age is for the browser; you can give them different values
- stale-while-revalidate means the visitor doesn't wait when the lifetime expires — the stale copy is served while a fresh one is fetched in the background
- immutable should only be sent when the filename is versioned; on an unversioned file it leaves the browser stuck with a year-old copy
Let the rule defer to the origin
In Delivery Rules, that path's rule needs Use browser cache time turned on and Cache Expire Time left empty.
- If you enter a lifetime, the origin's headers are ignored on that rule and the header sent to the browser gets rewritten too
- You can split rules by path: one rule for static files, another for pages
Measure, then expand
Try it on a single path first. Once you see the header you expect coming back and you're getting a HIT, move on to the other tiers.
How to see that it's working
Everything shows up in the response headers — you don't need to check the panel. Request the same URL twice:
curl -sI https://your-site.com/a-page | grep -iE "cache-control|x-proxy-cache-mt"
- X-Proxy-Cache-MT: MISS is normal on the first request — the content is being cached right then. The second request should return HIT.
- STALE is not an error: it means stale-while-revalidate is doing its job — the visitor gets the old copy while a fresh one is fetched in the background.
- If you see BYPASS, you're almost certainly logged into the site — a session cookie deliberately skips the cache. Try again in a private/incognito window.
- If the Cache-Control that comes back is different from what you sent, a fixed lifetime has been entered on that rule.
- If you also want to see what the origin sent, turn on origin diagnostic headers for the rule; X-Upstream-CacheControl shows what the origin said, Cache-Control shows what the visitor sees.
Three things that make the right header useless
- A response that sends
Set-Cookieis never cached. It doesn't matter how correct theCache-Controlis. This is the most common reason a cache never warms up: the application is setting a session cookie on every request. - With
Image Optimizationon for a rule, images are kept for 365 days and the origin's header is ignored. If you want to manage images yourself, turn this setting off for that rule. - Don't send
immutableon a file that isn't versioned. If the filename doesn't change, the browser keeps using the stale copy for a year, and a CDN purge won't fix that — purge only clears the edge, not the visitor's disk.
Next
- Cache-Control and max-age guide — what each directive does
- Cache-Control header generator — pick the directives and generate the header
- How to purge CDN cache — when purge is needed and when it isn't