Cache Key Design Patterns: URL, Headers, and Cookies
A cache key is the unique identifier a CDN uses to store and retrieve cached content. Every incoming request is mapped to a cache key, and the CDN checks whether a valid cached response exists for that key. The design of your cache keys directly determines your cache hit ratio — overly specific keys fragment the cache into millions of rarely-hit entries, while overly broad keys serve incorrect content to users who should see different responses. Mastering cache key design is one of the highest-leverage optimizations in CDN architecture.
What Is a Cache Key and How Does It Work?
When a CDN edge server receives an HTTP request, it computes a cache key from the request attributes and uses that key to look up stored responses. If a matching entry exists and has not expired, the CDN serves the cached response without contacting the origin. If no match is found, the CDN fetches from the next tier in the cache hierarchy or from the origin server.
The default cache key for most CDN providers consists of: For foundational context, read CDN Caching Strategies: Pull, Push, and Hybrid — FlyFish NWA.
scheme + host + path + query_string
Example:
https://example.com/images/hero.jpg?v=42
Key: https | example.com | /images/hero.jpg | v=42
This means that https://example.com/page?a=1&b=2 and https://example.com/page?b=2&a=1 produce different cache keys on most CDNs, even though they refer to the same resource. This is one of the most common sources of unnecessary cache fragmentation.
How Do Query Parameters Affect Cache Keys?
Query parameters are the most frequent cause of cache key bloat. Every unique combination of parameters generates a separate cache entry, even when the parameters have no effect on the response content.
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
Common problematic patterns include:
- Tracking parameters — UTM tags (
utm_source,utm_medium,utm_campaign), Facebook click IDs (fbclid), and Google click IDs (gclid) are appended by marketing tools but do not change the page content. - Cache busters — Random parameters like
?_=1719000000added by JavaScript libraries to prevent browser caching. These bypass the CDN cache entirely. - Session identifiers — Some legacy applications pass session IDs as query parameters instead of cookies.
- Pagination and sorting — Parameters like
?page=3&sort=datethat do change the response and should be included in the key.
The solution is to explicitly configure which query parameters are included in the cache key:
| Strategy | When to Use | Example Configuration |
|---|---|---|
| Include all (default) | API endpoints where every param matters | All query params in cache key |
| Include specific | Pages with meaningful params plus tracking noise | Include only: page, sort, category |
| Exclude specific | Pages with few tracking params | Exclude: utm_*, fbclid, gclid |
| Ignore all | Static assets where query strings are versioning only | Cache key uses path only |
| Sort parameters | Any endpoint where param order varies | Normalize ?b=2&a=1 to ?a=1&b=2 |
Stripping tracking parameters from cache keys alone can improve hit ratios by 10 to 25 percent for marketing-heavy sites. For a deeper look at how header values interact with caching, see our Cache-Control headers deep dive.
How Does the Vary Header Impact CDN Caching?
The HTTP Vary header instructs caches to include specific request header values in the cache key. When the origin responds with Vary: Accept-Encoding, the CDN creates separate cache entries for each encoding type: one for gzip, one for Brotli, and one for uncompressed responses.
Vary: Accept-Encoding is well-behaved because it produces only two or three variants per URL. Problems arise with broader Vary values:
Vary: User-Agent creates a separate cache entry for every distinct User-Agent string. With thousands of unique User-Agent strings in the wild (different browser versions, operating systems, device models), this effectively makes every request a cache miss. A single popular URL could generate 5,000 or more cache entries, none of which are shared across users.
Vary: Cookie creates a separate cache entry for every unique cookie value. Since session cookies are unique per user, this means zero cache sharing — every user gets their own copy. This negates the purpose of CDN caching entirely.
Vary: Accept-Language is borderline. If your site serves content in 5 languages, this produces 5 variants per URL, which is manageable. If the origin sends fine-grained locale headers like en-US, en-GB, en-AU for identical English content, you get unnecessary fragmentation.
The best practice is to keep the Vary header as narrow as possible. If you need content variation based on request properties, use custom cache keys or edge logic instead of Vary.
Why Are Cookie-Based Cache Keys Problematic?
Including cookies in the cache key is one of the most common CDN misconfigurations. It creates a per-user cache that defeats the shared caching model CDNs are designed for.
Consider a typical e-commerce site where every response includes Vary: Cookie because some pages show personalized content. The result:
- The homepage is cached 50,000 times (once per active session cookie).
- Each product page is cached 50,000 times.
- The cache hit ratio drops to near zero because each user's cookie value is unique.
- The origin handles nearly all traffic despite having a CDN in front of it.
Better approaches to personalization at the edge:
Edge Side Includes (ESI). Cache the main page template without cookies and use ESI to inject personalized fragments. The main page achieves high hit ratios while only the small personalized fragments require origin contact. See dynamic content caching for ESI implementation details.
Client-side personalization. Serve a generic cached page and use the browser to fetch personalized data from an API endpoint. The page itself is cacheable; only the API calls are per-user.
Selective cookie keys. Instead of varying on the entire cookie header, include only the specific cookie that determines the content variant. For example, if a country cookie determines pricing, include only that cookie (which has a small number of possible values) rather than the full cookie string.
How Can Device-Based Cache Keys Improve Mobile Performance?
Some sites serve different HTML or images based on the requesting device — a mobile layout versus a desktop layout, or WebP images versus JPEG. Including the full User-Agent header in the cache key is destructive, but a normalized device class can work well.
The recommended approach is to reduce the User-Agent to a small number of device classes at the edge:
# Edge logic pseudocode
if (request.user_agent matches mobile_pattern) {
cache_key.device = "mobile"
} else if (request.user_agent matches tablet_pattern) {
cache_key.device = "tablet"
} else {
cache_key.device = "desktop"
}
This creates at most three cached variants per URL instead of thousands. CloudFront provides this through device detection headers (CloudFront-Is-Mobile-Viewer, CloudFront-Is-Tablet-Viewer), which you can include in your cache policy. Cloudflare offers similar functionality through its CF-Device-Type header.
For image optimization specifically, consider using the Accept header with normalization: group clients into those that support WebP/AVIF and those that do not, producing only two or three cache variants for each image URL.
What Are Custom Cache Keys and When Should You Use Them?
Custom cache keys override the default URL-based key with a precisely defined combination of request attributes. Cloudflare, Fastly, and other enterprise CDNs offer this capability.
A custom cache key can include or exclude any combination of:
- URL components — Scheme, host, path, specific query parameters.
- Request headers — Accept-Encoding, Accept-Language, custom headers.
- Cookies — Specific named cookies (not the full cookie string).
- User properties — Device type, geographic region, protocol version.
A practical example for an e-commerce site:
# Custom cache key for product pages
Key components:
- Host: include
- Path: include
- Query params: include only "color", "size" (exclude utm_*, gclid)
- Headers: Accept-Encoding (normalized to gzip/br/identity)
- Cookies: include only "currency" (USD/EUR/GBP)
- Device: mobile / desktop (from User-Agent classification)
Result: max 2 devices x 3 encodings x 3 currencies = 18 variants per product URL
Compare this to the default behavior where including the full query string, all cookies, and the raw User-Agent could produce thousands of variants. Custom keys give you precise control over cache granularity.
How Does Cache Key Normalization Improve Hit Ratios?
Cache key normalization standardizes the cache key to eliminate trivial differences that would create separate entries for identical content. Normalization should be applied at the CDN edge before the cache lookup:
Query parameter sorting. Reorder query parameters alphabetically so that ?color=red&size=L and ?size=L&color=red produce the same cache key.
Case normalization. Lowercase the URL path so that /Products/Shoes and /products/shoes map to the same key. Only apply this when your origin serves identical content regardless of case.
Tracking parameter removal. Strip marketing parameters (utm_source, utm_medium, utm_campaign, utm_term, utm_content, fbclid, gclid, msclkid) from the cache key. These parameters are used for analytics and do not change page content.
Trailing slash normalization. Treat /about and /about/ as the same key, or redirect one to the other before the cache lookup.
Protocol normalization. If your CDN serves identical content over HTTP and HTTPS, remove the scheme from the cache key. Most modern sites serve HTTPS only, making this normalization unnecessary.
Implementing comprehensive normalization typically improves cache hit ratios by 10 to 30 percent, depending on how much fragmentation existed before. The improvement is most dramatic on marketing-heavy sites with many inbound campaign links.
What Are Common Cache Key Anti-Patterns?
Certain cache key configurations cause persistent problems that are difficult to diagnose because they silently reduce hit ratios without producing errors:
| Anti-Pattern | Symptom | Fix |
|---|---|---|
| Vary: Cookie on all responses | Near-zero hit ratio, high origin load | Remove Vary: Cookie, use ESI or client-side personalization |
| Vary: User-Agent | Thousands of cache entries per URL | Normalize to 2-3 device classes |
| Including session cookies in key | Per-user caching, no sharing | Include only content-affecting cookies |
| Random cache busters in query | Every request is a cache miss | Use filename hashing for versioning instead |
| Not sorting query parameters | Duplicate entries for same content | Enable query param sorting at edge |
| Including Accept header in key | Fragmentation from minor Accept variations | Normalize to supported content types only |
To diagnose cache key issues, examine the X-Cache response header. If you see frequent MISS responses for content that should be cached, the cache key is likely too specific. Use your CDN's analytics dashboard to identify URLs with high miss rates and inspect what key components are creating unnecessary variants.
Effective cache key design requires balancing correctness (different content must have different keys) against efficiency (identical content must share keys). Start with the narrowest key that produces correct responses, then widen only where content truly varies. Every additional component you add to the cache key multiplies the number of cached variants and reduces the probability that any single request finds a cache hit. When combined with proper TTL optimization and invalidation strategies, well-designed cache keys form the foundation of a high-performance CDN configuration.