At the edge, a CDN cache key decides when two requests are allowed to reuse one stored response. If the key ignores a request detail that changes the body, one visitor can receive the wrong variant. If it includes every incidental header, cookie and query parameter, the edge stores thousands of nearly identical objects and the hit ratio collapses. The safe design is the smallest key that identifies one genuinely shareable response.
For developers and platform engineers, the required starting knowledge is modest: you should be able to inspect an HTTP request and its response headers. Shared cache, representation and cardinality are defined where they affect the decision. The objective is an architecture contract you can translate into Cloudflare, Google Cloud CDN, Fastly, Varnish or another managed cache—not a click path tied to one dashboard.
CDNs use a cache key as the identifier for looking up a stored response. Most managed products begin with some form of scheme, host, path and query string, then let operators include, exclude or normalize selected components. Cloudflare’s current cache-key reference documents query strings, headers, cookies, host and user features as possible inputs; other providers expose similar ideas with different defaults and plan limits.
Before changing those inputs, write one sentence that must remain true:
> Any two requests that resolve to the same edge key receive a response that is safe and correct for both requesters.
That sentence is the response invariant. It makes correctness testable. A language preference may produce a small set of public variants. An account dashboard produces data tied to one identity. A campaign tag may change analytics without changing the body. Those are three different decisions even though all three details arrive in the request.
Start the inventory from application behavior, not the CDN menu. For every route family, record whether the response changes with authentication, authorization, language, currency, device capability, query filters, host or API version. Then ask whether each changed representation is safe to share among everyone who has the same value.
Shared caches reuse stored responses across clients. RFC 9111 and MDN’s HTTP caching guide distinguish that behavior from a private browser cache. Personalized content placed in a shared cache can expose one user’s data to another, so privacy classification comes before hit-rate optimization.
Some pages are public but have a bounded number of legitimate representations. Examples include a documentation page in en or fr, prices in a small declared currency set, or an image response negotiated between supported formats. When the application returns the same body to every requester inside one variant, that language, currency or format can belong in the key.
Bounded is important. A cookie named currency=EUR may create three or five reusable variants. A cookie containing a random visitor ID creates one variant per browser and almost no reuse. Provider features for named-cookie variation, such as Google Cloud’s custom cache-key controls, do not make every cookie a good key dimension.
Authentication and authorization change more than presentation. A dashboard, order history, private lesson, saved address or account-specific API response is tied to a principal and its permissions. Adding the complete session token to the key may prevent two sessions from colliding, but it also stores sensitive responses at a shared edge and creates effectively unbounded cardinality.
Prefer a clear bypass rule for authenticated or private routes, backed by origin response directives such as Cache-Control: private or no-store where appropriate. The exact managed-cache behavior still needs provider verification because operator rules can override origin headers. Google Cloud warns that its FORCE_CACHE_ALL mode is unsuitable for private, user-identifiable content; that boundary is more important than a higher hit percentage.
Membership and ecommerce paths make the distinction concrete. Voxfor’s logged-in workload model separates cacheable public pages from member dashboards, protected content, payment events and password recovery. A page cache can accelerate the first group without becoming the identity system for the second.
Cardinality is the number of distinct values a component can produce. Each added dimension multiplies the possible object count for one path. Two languages and three currencies can create six variants. Add 20 device labels and the theoretical space becomes 120. Add a unique session ID and useful reuse disappears.
Query parameters deserve individual decisions. Keep a parameter when it changes the representation—page number, product filter, API version or search term may be functional. Exclude a parameter only after proving it does not change the body, such as a campaign identifier used solely for analytics. Never ignore the full query string just to improve hit rate when any parameter controls content, access or routing.
Headers have the same multiplication risk. Accept-Encoding or a small normalized image-format capability may produce useful variants. Full User-Agent, arbitrary Accept-Language strings and request IDs have very high cardinality. MDN specifically warns that varying on User-Agent drastically reduces reuse; normalize to a small supported capability set when the response truly differs.
Cookies should be allowlisted by meaning, not included wholesale. A consent-state or language cookie might represent a bounded public choice. Session, CSRF, cart, experiment assignment and visitor-tracking cookies need separate analysis. Some should trigger bypass, some should never affect the body, and a few may be safe bounded variants. Treating the entire Cookie header as one key dimension hides those decisions and creates unstable objects as unrelated cookies appear or change.
HTTP edge caching is also different from application object caching. Redis may reduce repeated database work even when a page cannot be safely shared. Voxfor’s Redis object-cache guide and its deeper Object Cache Pro analysis explain that layer; neither turns a personalized HTML response into public content.
A useful policy records cache eligibility separately from key composition. “Cookie present” is not one answer: the route, response and cookie purpose decide whether to bypass, partition or ignore it.
| Route or representation | Shared-cache decision | Key dimensions | Acceptance evidence |
|---|---|---|---|
| Versioned CSS, JS, fonts or images | cache publicly with long freshness | host + normalized path; format only if body differs | repeated request becomes a hit; hash matches origin release |
| Public article with analytics parameters | cache publicly | canonical path; exclude proven tracking-only parameters | tagged and untagged URLs return identical body and key result |
| Public language variant | cache bounded variants | path plus normalized language value | each supported language is correct; unsupported values follow one documented fallback |
| Search or filtered listing | cache only when freshness and query behavior are acceptable | allowlisted functional parameters with normalized order | different filters never collide; equivalent parameter order does not fragment |
| Login, checkout or account dashboard | bypass shared cache | none; route or authentication signal makes response ineligible | two sessions never receive a cached response from each other |
| Public API with versioned schema | cache only when authorization and freshness permit | host + path + functional query + API version | schema/version changes partition correctly; authorized responses bypass |
The table is a design artifact, not a provider configuration. Translate each row into the effective rules your CDN applies, including rule order. A later broad “cache everything” rule can defeat a carefully written private-route exception.
Normalization belongs in the same contract. Decide whether query parameter order, case, trailing slash, duplicate parameters, percent encoding and origin rewrites represent the same resource. Cloudflare recommends aligning URL normalization at the edge and origin when custom keys are active, partly to prevent inconsistent behavior and cache-poisoning opportunities. Consolidate only requests that the origin also treats as equivalent.
Treat a key change as a behavior release. Save the current rule set, choose a small route cohort, define rollback and purge boundaries, then observe cache status, origin traffic and response correctness together. A lower origin request rate is not a pass if the wrong representation is being reused.
Use controlled test accounts and synthetic data. Send secrets through your normal secure test process; do not paste production session tokens into a shared shell history or article. The following examples show the request shape with placeholders:
curl -sS -D anon-1.headers -o anon-1.body 'https://example.com/catalog?utm_source=qa'
curl -sS -D anon-2.headers -o anon-2.body 'https://example.com/catalog'
cmp -s anon-1.body anon-2.body && echo 'tracking parameter does not change body'
Run the anonymous pair more than once at the same edge location. Inspect the CDN’s documented cache-status header, Age where meaningful, and its trace or log facility. A body match alone does not prove the effective key; both requests might have missed independently.
For a private route, use two separate controlled sessions and compare each response with its expected identity marker:
curl -sS -D user-a.headers -o user-a.body -H 'Cookie: session=TEST_SESSION_A' https://example.com/account
curl -sS -D user-b.headers -o user-b.body -H 'Cookie: session=TEST_SESSION_B' https://example.com/account
The pass condition is stronger than “the bodies differ.” Each body must contain only its expected synthetic account data, neither request may receive the other’s cached object, and the effective edge result must show bypass or another explicitly approved private-delivery behavior. Repeat in both orders so a warm object from User A cannot silently become the source for User B.
Changing key composition may leave older objects reachable under old or overlapping keys. Google Cloud’s cache-key documentation notes that changing the key creator does not necessarily invalidate existing entries. Decide whether deployment requires a targeted invalidation, a versioned path, TTL expiry or a full purge; then prove the chosen boundary.
Validate configuration before activation and reload without discarding the recovery path. Voxfor’s Caddy proxy change workflow provides a transferable pattern: back up, validate, apply one bounded change, test the public result and retain a known rollback.
After release, track cache hit ratio by route and variant, origin requests, error rate, key cardinality where the provider exposes it, and customer-path correctness. A sudden hit-ratio fall after adding a header or cookie usually indicates fragmentation; an abrupt hit-ratio rise after removing a functional dimension can indicate dangerous consolidation. Both changes need body-level sampling, not a dashboard verdict alone.
Only request dimensions that change a response which is safe to share among all requesters with that same value belong in the key. Start with scheme, host and normalized path as required by the provider, then add only proven functional query, header or bounded-cookie variants.
Usually not. Account-specific sessions should normally bypass shared caching because one key per session creates unbounded fragmentation and stores private responses at the edge. Use provider-specific private-content controls and verify the effective result with two separate test sessions.
Vary: Cookie enough to protect personalized content?No. Vary can tell a compliant cache that a response depends on a request header, but product behavior, overrides and cardinality still matter. MDN recommends Cache-Control: private rather than cookie variation for personalized content; confirm how the selected managed CDN treats both directives.
Ignore only parameters proven not to change content, authorization, routing or response semantics. Tracking-only parameters are common candidates. Search, filters, pagination, API versions, signatures and feature switches usually require inclusion, normalization or cache bypass according to the route.
Warm the route with controlled User A, request it with controlled User B, then reverse the order. Verify each body against an account-specific synthetic marker and inspect the CDN’s cache-status or trace evidence. Neither session may receive the other’s representation.
Every added high-cardinality component creates more possible objects for one URL. Full cookies, user agents, request IDs or unique query values split traffic across cold variants. Remove only dimensions that do not change a safely shareable response; correctness remains the first constraint.
Close the change with a compact record: affected route families, public/private classification, included and excluded dimensions, normalization rules, maximum expected variant count, origin directives, provider rule order, purge decision, rollback reference and test evidence from anonymous plus two-session requests.
Synthetic monitoring should keep checking the decisive paths after the rollout. Voxfor’s customer-journey monitoring guide shows how to test more than a green homepage, while its Website Performance archive provides related caching and delivery material.
A high hit ratio is useful only inside a correct sharing boundary. The durable rule is simple: partition bounded public variants, bypass identity-bound responses, ignore noise only after proving equivalence, and keep evidence that the edge still serves the right representation to the right requester.