Traffic and messaging
Cache control and cache keys
The cache key says which requests count as the same object, and Cache-Control headers say how long to keep it. Get the key wrong and you waste the cache or leak private data.
A CDN has to answer two questions for every request. Which stored object does this request match? And how long may that object be served? The first answer is the cache key. The second comes from Cache-Control headers that your origin sends. Both decide your hit ratio, and both can leak data if they're wrong.
Concept
A cache key is the set of request parts that identify an object, usually the host, path and query string. A validator is a version tag, such as an ETag, that lets a cache ask "has this changed?" without downloading it again.
The big idea
Think of the cache key as a label on a shelf. Items with different labels are stored separately. If you put the user's name on the label, each user gets their own shelf. If you leave it off, everyone reaches for the same item. Labels that are too detailed waste shelf space. Labels that are too vague hand out the wrong item.
Walking through it
The origin tells caches what to do with the Cache-Control response header.
| Directive | Meaning |
|---|---|
max-age=N | Fresh for N seconds in any cache |
s-maxage=N | Overrides max-age for shared caches such as CDNs |
public / private | private allows only the user's browser to cache |
no-cache | Store it, but check with the origin before each use |
no-store | Never store it anywhere |
immutable | This URL will never change, so don't revalidate |
stale-while-revalidate=N | Serve stale for N seconds while fetching a fresh copy |
stale-if-error=N | Serve stale for N seconds if the origin errors |
stale-while-revalidate and stale-if-error are underused. The first hides refresh latency. The second keeps your site up while the origin is down.
Validators make revalidation cheap. The origin sends an ETag or Last-Modified. When a cached copy expires, the CDN asks, If-None-Match: "abc123". If nothing changed, the origin answers 304 Not Modified with no body.
Cache keys are where most hit ratios are lost.
- Query strings.
?utm_source=twitterand?utm_source=emailare separate keys for the same page. Strip marketing parameters. Varyheaders.Vary: Accept-Encodinggives a few variants, which is fine.Vary: User-Agentgives thousands and effectively disables caching.- Normalize. Lowercase paths, sort query parameters, and map device types to a few values such as
mobileanddesktop.
The opposite mistake is worse. If the key leaves out something the response depends on, users get each other's content. Steam had an incident in December 2015, during a traffic surge, where a caching problem showed some users other people's account pages.
Warning
Don't let a CDN cache responses that set cookies or depend on the Authorization header, unless the cache key was designed for that. Most CDNs skip these by default. Overriding the default is how account pages leak.
Common mistakes
Vary: User-Agent. Every browser variant gets its own entry, so most requests miss.- Tracking parameters in the key. Each campaign splits the cache for the same page.
- Personal responses without
private. Anything per-user needsprivateorno-store, unless the user is part of the key.
Check yourself
- Why does
Vary: User-Agenthurt the hit ratio? Each distinct User-Agent string gets its own cache entry, so most requests miss. - What should a personalized response use?
privateorno-store, unless the user or segment is explicitly part of the cache key.
Key takeaways
- The cache key defines what counts as the same object. Keep it as small as the response allows.
s-maxage,stale-while-revalidateandimmutablecontrol freshness at the CDN.- A key that leaves out a per-user detail leaks data. A key with too much detail wastes the cache.
Further learning
MDN: Cache-Control lists every directive with examples.
Next, read about purging and versioned URLs, which covers how to change content already in the cache.
Related
CDNs and the edge
Serve content from points of presence near users. A CDN cuts latency, absorbs attacks and cuts bandwidth costs, and its cache keys, headers and purge rules decide how well it works.
Caching
Where to put a cache, how to read and write through it, how to size it from hit-rate math, and how to keep it from serving stale data or melting down.
HTTP/1.1, HTTP/2 and HTTP/3
The protocol of the web. Separates HTTP's meaning (methods, status codes, caching) from its wire format, and shows how each version fixes the latency problem of the one before.