CDN Cache Keys: The Small Decisions That Decide Your Hit Rate
Cloud CDN's cache key is not just the URL; default configurations incorporate cookies, headers, and query strings, meaning small variations in requests can create a split…

What’s in this piece
Cloud CDN's cache key is not just the URL; default configurations incorporate cookies, headers, and query strings, meaning small variations in requests can create a split cache, decreasing hit rates.
Default key, default fragmentation
Delivering content from a CDN starts with a cache hit. But the default rules for cache keys mean this is much less reliable than we might assume. According to Google Cloud's documentation, a CDN cache key typically includes the full URL, any named headers, and all cookies. In other words, two requests that reach the same page but use different cookies, or have slightly different URLs, will be treated as distinct.
Cloudflare's documentation on cache keys confirms this; its default key also includes the full URL, meaning a /blog?utm_source=google URL will be treated as a separate key from /blog?utm_source=linkedin, or even from /blog. So small navigation differences, even folder structures, can break the cache and send the request to the origin instead.
Google documents that the cache key is built from the request, including the URL, cookies, and named headers. And this can mean a single request can arrive on the cache multiple times, as the request can be consolidated in the cache each time a sufficient subset of the key repeats.
This sophistication is fully justified. Requests are often personalized, and fragmenting the cache is a way of delivering the right content. But cache key control isn't limited to the URL, it belongs to any configured headers, cookies, or query strings.
Query strings as the easiest source of accidental misses
Most CDNs, including Google Cloud, default to caching based on the full URL. This means that a request to /blog with no parameters, /blog with both query strings included, and /blog with a tracking parameter — all of these would be treated as distinct keys.
Even Cloudflare's default caching behavior, it states on its page about understanding cache keys, treats the full URL as part of the key.
The upside is that no special configuration is required for small differences like language or page number to be treated as distinct keys. But the downside is easy to encounter. Any slight variation, like a tracking code, can create a new cache key. In an ecommerce context, think about product variants: it's common to pass filters and customizations in the query string. Each variant, filtered or customized, needs to be separately cached — and this means a broader cache footprint and more reads from the origin.
Cloudflare explicitly allows caching with or without parameters, including ignoring the entire query string. And Gcore's support docs on cache hit ratios make the same recommendation: filter out tracking parameters, or even cool the query string, if it makes sense for the app.
Cookies and personalized requests
Query strings aren't the only thing that can create a separate cache key. Cookies can do the same, whenever the platform supports it.
Google Cloud lets users add named cookies to the cache key, making cookies a deliberate part of the key configuration. This means that a cookie, once added to the key, can fragment the cache across signed-in and signed-out requests, or even fragment it further among signed-in requests.
AWS also notes that cookies are part of the cache key, and even that they're part of a reverse-proxy pattern suitable for personalization. The key point is that cookies, unlike query strings, are generally tied to the user.
A closer look at Cloudflare's documentation reveals they also let users choose cookies to include or exclude, whereas by default, only HTTP headers and the full URL are included. They even support an inclusion rule that triggers on a cookie name or value. Cookies are inherently personal, which makes them a natural candidate for caching: a key that includes them can be personalized to the signed-in user.
But Gcore's docs advise against this for public content. Instead, they note that in most cases, when cookies don't represent something cache-busting like a signed-in state, they're best excluded. Google's docs [confirm this: after the third request, content is cached. But that's with headers and cookies included. If the content doesn't really vary between signed-in and out, that's a wasteful configuration.]
Headers and controlled variation
Cookies and query strings aren't the only cache-busting part of the request. It happens with headers, too. Google Cloud states that its cache key, the thing that determines which cached copy to serve, is the URL plus any named headers.
Each of these settings can be configured in a CDN. AWS note that the cache key can also be configured by rules, specifying exactly which cookies, headers, and query strings create a new cache key. Indeed, AWS's own blog page includes a static-content pattern with no cookies or query strings, which it contrasts with a reverse-proxy/SSR pattern that includes them.
These are deliberate decisions, though, and not automatically part of the cache key. Cloudflare notes that you can include headers with a yellow key icon, such as a query, language, or device setting. And Google cloud notes the same, stating that headers, as configurables, can appear in the cache key
How to measure whether the cache is being fragmented
It's one thing to say that varying query strings or cookies increases the number of cache keys. But how much does that matter? [Is there a way to measure this, and avoid making the cache too fragmented?] The most explicit source on this is Cloudflare's own documentation on cache keys; it notes that this level of cache key configuration can reduce cache fragmentation, at the cost of some personalization. They even link to an older guide by Cloudflare, on improving cdn hit-rate, which bundled it with a bunch of other cache-optimization techniques. These ideas go back a long way; the blog post cites a 2015 article on optimizing cache hit ratios, in which the point was simply to exclude sensitive information from the cache.
In practice, Cloudflare's support docs recommend ignoring query strings for most requests, which implies a measurable cache hit ratio improvement. But Google's docs don't measure fragmentation, they only discuss edge cases, like cookies and headers, that are supposed to be included or excluded. Cloudflare's documentation sets the cache key as a map. gives some control over which keys are included. But Gcore's support docs on cache hit rate add that there are configurable options to exclude cookies and query strings from the cache.
So before diving into the caching details,(https://docs.cloud.google.com/cdn/docs/caching) Each CDN should offer a cache-hit ratio, measuring the number of requests that had a cached version to serve. This won't fit Google's definition of cache fragmentation, but examining it across resources that vary by cookie, header, or query string should let you see if fragmented keys are to blame.
Another metric mentioned by Cloudflare's own documentation is cache-by-country. But this isn't so much about fragmentation as about serving a faster version of the content that's tuned to the region. If the final CDN cache is always selected from the closest server in that country, though, a default configuration means that a search sweep from another country would stale the entire cache in that region.
When the safest cache key is the smallest one
Where privacy is to be protected, or when the data is the most personalized, it's safest to let the CDN bucket as it chooses. Where query strings, cookies, and headers express something fundamental to the content — something that the cache has to represent to mean anything at all — put it in the cache.
But where those parameters are hinting at variations that the cache can ignore, randomly switching content, or where the variation in cookies and headers is an accident of the request — in those cases, the smallest cache key is the safest one. Cloudflare recommends this, allowing the entire query string to be ignored on a configuration basis. AWS advises that this is exactly the configuration for static content, while full caching of cookies, headers, and query strings should be saved for the most personalized, reverse-proxy use cases.
- 01Infrastructure
Real-Time Event-Driven Architectures for Live Odds (Kafka Case Study)
It was derby night. At 20:07, traffic jumped. We hit 1.8 million requests per second. Our p99 moved past 380 ms. Odds on two hot markets went stale for 19 seconds.…
- 02Infrastructure
Email and Push Deliverability: Keeping Players Engaged Without Spam
You send one more promo. Then two. Then a late-night push. Results look fine for a week. After that, complaints spike, inbox rate drops, push tokens decay, and…
- 03Infrastructure
The Rise of Live Dealer Tech: Streaming Infrastructure Behind Modern iGaming
Warm light hits the felt. A dealer smiles. A wheel spins. A tiny sensor blinks. In under two seconds, a phone lights up on a train, and a player taps a chip. This…
- 04Infrastructure
Exactly-Once Is a Promise About Your Consumer, Not Your Queue
Kafka's famous "exactly-once" guarantees don’t mean what you think they do. While Kafka can make sure a message is delivered from one Kafka topic to another—without any…
