Performance guide
CDN Cache Misses: How to Find and Fix the Real Causes
A cache miss is a symptom. The fix depends on whether the object is absent, expired, uncacheable, or keyed differently than you expect.
Fix CDN cache misses by first classifying the response, then tracing its cacheability and cache key. Do not raise a TTL or enable broad HTML caching as a first reaction. A response can be a legitimate miss, a deliberate bypass, a revalidation, or a cache entry that is fragmented across URLs and headers. The safe goal is not the highest hit ratio; it is the lowest origin work consistent with correct and private responses.
An edge cache stores a representation under a key. On a request, it checks whether the key matches, whether the stored response is fresh, and whether policy allows reuse. If not, it contacts the origin or another cache tier. The origin response then either populates the cache, updates an existing entry, or remains uncacheable.
Do not optimize the wrong number
A higher hit ratio can look better while users still wait on slow misses, and a lower ratio can be correct when most traffic is private or intentionally dynamic. Segment cache performance by URL class, status, region, and provider.
Identify the cache outcome
Inspect response headers from more than one location and repeat the same request. With Cloudflare, CF-Cache-Status distinguishes common outcomes such as HIT, MISS, EXPIRED, REVALIDATED, UPDATING, STALE, BYPASS, and DYNAMIC. Age is additional evidence that a response came from a cache. With Fastly, inspect X-Cache, X-Served-By, Age, and your configured log fields. Provider labels and aggregation rules differ, so do not compare them as if they were one standard metric.
Use a request with a fixed URL, method, host, and relevant headers. Send it twice from the same test location, then from a second location. A first-request miss followed by a hit is normal cache fill. A miss on every request suggests a key mismatch, a non-cacheable response, a bypass rule, an object too large for the configured cache, or a request path that never reaches the expected cache.
Revalidation is different from a full miss. The cache has an object but must ask the origin whether it changed, often using ETag or Last-Modified. A 304 response can save the body transfer but still costs an origin request and round trip. stale-while-revalidate can serve a stale response while updating in the background, if its semantics are appropriate.
Find the real cause
The response is not cacheable
Check the origin response for Cache-Control: private, no-store, or no-cache, and for Set-Cookie. Check whether the request carries Authorization, whether the method is GET or HEAD, and whether the status is eligible for storage. A dynamic response is often correct: account pages, cart contents, payment steps, and personalized recommendations should not be shared accidentally.
For public content, return an explicit policy rather than relying on heuristic freshness. A typical immutable asset might use a long max-age with a fingerprinted filename. A public HTML response may use a shorter shared-cache lifetime and revalidation. s-maxage can separate shared-cache freshness from browser freshness. stale-if-error may protect a public page during a temporary origin failure, but it must not mask dangerous or time-sensitive changes.
The cache key is too broad or too narrow
Query strings are frequent offenders. Analytics parameters can create many keys for one representation, while language, currency, device, or content experiment parameters may genuinely change it. Headers named by Vary, cookies, authorization, hostnames, and URL normalization can also split the cache. Document every key component and remove only values proven not to affect the response.
Cloudflare equivalents include Cache Rules, custom cache keys, Cache Analytics, and Trace. Fastly equivalents include VCL hash logic, surrogate keys for invalidation, and shielding. Keep the provider-neutral key model in source control and review it with the application team. Never remove a user or tenant discriminator from a key to improve a dashboard metric.
The object is cold, expired, or evicted
A low-traffic object can expire before its next request. A deploy or purge can make a whole site cold. A large object or memory pressure can lead to eviction. In a multi-POP CDN, one location can miss while another has the object. Tiered caching or shielding can reduce the number of origin fills, but it does not make every edge POP hold every object.
If content is published predictably, warm a small set of public URLs with a controlled process. Prefer versioned filenames and targeted purge over purging an entire site. Longer TTLs reduce fills but increase staleness risk, so pair them with a reliable invalidation method.
The request never reaches the cache
A worker, edge function, redirect, WAF action, or application middleware may run before the cache. A cache rule may be ordered after a bypass rule. A different hostname, protocol, path, or origin route may be serving the test. Trace the request through the provider and compare edge logs with origin logs.
A safe troubleshooting workflow
- Pick a public, deterministic URL and record status, response headers, content length, and body version.
- Repeat the request with and without harmless tracking parameters, then with relevant language or device headers.
- Compare a cold request with the second request from the same POP or test region.
- Inspect origin headers, provider rules, cache-key configuration, and purge history together.
- Fix one cause in a narrow path, then verify privacy, content correctness, origin request rate, and cache status.
- Roll the change out by hostname, path, or region before applying it globally.
Observe what users experience
Track hit, miss, bypass, revalidation, and stale rates separately. Break them down by route, status code, response size, region, CDN, cache key version, and deployment. Correlate cache outcomes with origin CPU, bandwidth, TTFB, and error rate. Sample full headers in logs, but protect cookies, authorization values, and personal data.
Mistakes include caching all HTML, treating no-cache as no-store, ignoring Set-Cookie, stripping every query string, measuring only aggregate hit ratio, purging on every deploy, and assuming a provider's HIT means the browser did not make a request. A CDN reduces origin work when policy is correct; Multi-CDN adds another cache and purge consistency problem to solve.
For standards-based behavior, read RFC 9111 HTTP Caching. For implementation details, use Cloudflare cache responses and Fastly shielding. Contact Optimi if you need a cache-key and origin-load review.
There are only two hard things in Computer Science: cache invalidation and naming things.
Turn cache misses into useful signals
Talk to our team about cache keys, TTLs, purges, shielding, and observability across your delivery stack.
Review your cache