Cache key and Vary — when 'same URL' isn't
The cache key defaults to method + URL; the Vary response header adds request-header values to the key, multiplying entries per URL — and Vary: User-Agent shatters one cacheable response into thousands of near-duplicates.
Purge invalidates entries — but what determines which entries are matches in the first place? The cache key, and the Vary header that quietly multiplies it.
Scene 08
Cache key and Vary — when 'same URL' isn't
- Watch
- Try it
- Predict
- Capture
Vary: Accept-Encoding only. Three entries per URL (gzip / br / identity). As requests pour in, the hit-ratio gauge climbs and memory stays low — every browser's encoding lands on one of the three cached entries.
Highlighted lines are the ones running in the diagram right now.
def compute_cache_key(req, vary):# the default identity: method + full URLkey = req.method + ' ' + req.url# Vary tells the cache to also key on these headersfor axis in vary:v = req.headers.get(axis, '')key += '|' + axis + '=' + vreturn hash(key)
def vary_axes_for(url):resp = cache.peek_response(url)# parsed from the origin's `Vary:` response headerreturn resp.headers.get('Vary', '').split(',')# e.g. ['Accept-Encoding'] -> 3 entries# ['Accept-Encoding','Accept-Language'] -> 24# [...,'User-Agent'] -> ~5000+
Where this sits in Build a CDN
Scene 08 of 13, in the Control act — Purge flavors, the cache key, and the Vary footgun.. The cache key defaults to method + URL; Vary multiplies it by request-header values — Vary: User-Agent shatters one URL into thousands.
Up next. Even with a perfect cache key, a popular object expiring across hundreds of POPs at once stampedes origin — unless we put one POP between them.