Common reasons Cloudflare fails to cache your content
By default, Cloudflare only caches a predefined list of static file extensions (images, CSS, JS, fonts). HTML pages and dynamic application routes are passed directly to your origin with cf-cache-status: DYNAMIC. Furthermore, several technical factors commonly prevent caching:
- Conflicting origin HTTP headers: Directives like
Cache-Control: no-store,private, ormax-age=0force Cloudflare to bypass edge caching entirely (statusBYPASS). - Unintended Set-Cookie headers: If your backend framework (WordPress, Laravel, Node.js) issues session cookies on public pages, Cloudflare prevents edge caching to avoid cross-user session leakage.
- Fragmented Query Strings: Marketing and analytics tracking parameters (UTMs, gclid, fbclid) create distinct cache keys for identical assets, resulting in repeated cache
MISSevents. - Conflicts between legacy Page Rules and modern Cache Rules: Outdated rule ordering can override edge TTL instructions and cause unpredictable caching behavior.
A proven approach to reaching 80%+ cache hit ratios
To turn Cloudflare into an effective performance shield without breaking interactive application features:
- Implement granular Cache Rules: Define specific Edge TTL rules with automatic bypass when authentication, checkout, or cart cookies are present.
- Separate Browser TTL from Edge TTL: Leverage the
s-maxageheader or Cloudflare edge settings to keep resources cached in edge nodes while maintaining control over client-side freshness. - Normalize Query Strings: Strip or reorder tracking parameters to unify cache keys without degrading analytics tracking.
- Enable Tiered Cache: Direct regional edge data centers to pull from centralized upper-tier hubs, drastically reducing round-trips to your origin infrastructure.
CF Garage