CDN Cache Key Design: The Knob That Decides Your Hit Rate

March 29, 2026


A CDN is a hash table with a million entries and a hit rate dashboard. Everything interesting about its performance is decided by the key you choose to hash.

The default key is (host, path, query string). That sounds reasonable until you look at what flows through real traffic. The same product page arrives as /products?category=shoes&sort=price and /products?sort=price&category=shoes. Two cache entries, one object. Now multiply by every permutation a frontend can produce and you have shredded the cache before anyone clicked anything.

The first rule is to normalize before hashing. Sort query params alphabetically. Whitelist the ones that actually change the response, like category, sort, and page. Strip the rest. The dangerous category is tracking parameters: utm_source, utm_campaign, fbclid, gclid. They never affect the rendered HTML, but every campaign creates a unique URL, and every unique URL is a new cache entry.

Headers fragment too. Vary: Accept-Encoding is healthy because gzip and brotli responses really are different bytes. Vary: User-Agent is a trap. Modern UA strings have so much entropy that you end up with one cache entry per browser build. The fix is device-class binning at the edge: classify the request as mobile, tablet, or desktop in a worker, set a single header, and vary on that.

Locale and A/B bucket belong in the key when they change the response, not as raw cookies. Compute a small bucket string at the edge, fold it in, and your variants stay countable.

The hit rate math is unforgiving. If you have 100 popular URLs and one tracking param with 50 distinct values, you do not have 100 cacheable objects. You have 5,000. The popular tail thins out, the long tail explodes, and origin load grows linearly with permutations.

The production failure is almost always the same. A marketing team launches a campaign. Every outbound link, email, push notification, and ad gets utm_source, utm_medium, and fbclid appended. Each click writes a brand new cache key into every POP. Hit rate falls from 90 percent to 12 percent over a single afternoon. Origin saturates, p99 latency triples, and the on-call engineer spends two hours staring at green CPU graphs in the CDN dashboard while the database is on fire.

The rule of thumb: make the key as coarse as correctness allows. Then audit what is actually getting hashed in production, because someone will add a param you did not plan for. Log the raw key on a sampled basis at the edge and graph the cardinality. If the count of distinct keys per URL path drifts upward week over week, you have a fragmentation leak. Fix it before the next campaign.

Key takeaway

A cache key should be as coarse as correctness allows. Every extra dimension you fold in halves your hit rate, and tracking params are the silent killer.

Originally posted on LinkedIn. View original.


All Rights Reserved.