Cache-Control directives received from the origin server. Free, Pro, and Business customers have this option enabled by default and cannot disable it.
Cloudflare's Cache Rules allows users to either augment or override an origin server's Cache-Control headers or default policies set by Cloudflare.
When fetching a resource from the origin, Cloudflare looks at the response and applies the following default cache behavior:
If there is no Cache-Control or Expires, CloudFlare caches responses (with varied TTL) only when the origin status code is one of 200, 206, 301-303, 404 and 410.
In other words:
all resources with cacheable extensions will be cached unless you have headers that tell Cloudflare otherwise
redirects and 404s will be cached
errors such as 500 won’t be cached
(NOTE: Your zone settings may override this behavior, and there are additional specifics I haven’t covered - e.g. cacheable size limits, Set-Cookie handling, and more. When in doubt, always refer to the official documentation.)
How to extend cached resources to HTML (and others)
You have understood by now that most of the pages making up your website (HTML, JSON, ...) are not even considered for caching - even though they would likely benefit from it!
You may believe changing this behavior is tricky and requires a deep knowledge of your pages and Cloudflare. What if I tell you it only requires a teeny-tiny generic rule at the right place?
Indeed, assuming your application is configured to return relevant cache-control headers, the magic comes in one of two forms:
- either create a new Page Rule matching
* and setting Cache-Level: Cache Everything
Page Rule Cache Everything
- or use a Cache Rule with a similar yield:
Cache Rule Cache Everything
(Cache Rules are now preferred over Page Rules).
It may sound weird (especially the page rule), but this will promote all resources to cacheable (a.k.a. eligible for cache). If you followed along, you know that it doesn’t impact the next step of the process: Cloudflare will still use the Cache-Control headers and status code to make the final cache / no cache decision.
In other words, your admin pages (with a proper Cache-Control: private, no-store, no-cache) and pages with a session cookie won’t be cached, but now your HTML home page (with a proper Cache-Control: public, max-age=3600) will!
Once this rule is on, the number of DYNAMIC pages (uncacheable) will reduce drastically. You may still need to fine-tune the behaviors, but at least it will provide a decent baseline to work with.
I was initially confused by Cloudflare’s caching behavior, especially when HTML pages returned a DYNAMIC cache status. The documentation is extensive but overwhelming and I spent quite a few hours on it, trying to figure it out. The redaction of this article helped clarify everything in my head.
The rule shared in the last section is something we use in production. Without it, the cache gains would be far less tangible.
I can only hope it helps you too. Don’t hesitate to drop a like or a comment, your reactions always make me smile 🤗.