Cloudflare caches static files by default and leaves HTML alone. That surprises people in both directions: they expect their pages to be cached and see slow origin hits, or they expect a changed file to appear instantly and keep seeing the old one. This guide covers how the cache decides, how to check what happened to a request, how to write cache rules, and how to purge safely.
Cloudflare's dashboard, rule limits, and purge options differ by plan and are updated regularly. Names below follow current Cloudflare terminology (Cache Rules and the Purge Cache page), but confirm the exact menu locations and plan limits in Cloudflare's own documentation before relying on them.
What Cloudflare caches by default
By default Cloudflare caches responses for requests to files with certain static extensions, such as images, stylesheets, scripts, fonts, and archives. It does not cache HTML or JSON by default, because those are often dynamic. Cloudflare publishes the list of default-cached extensions; check it if you are unsure about a specific file type.
Default behavior also respects what your origin says. The key signals:
Cache-Control: no-storeorprivateprevents edge caching.Cache-Control: max-age=...ands-maxage=...set how long a cached copy is considered fresh.s-maxageapplies to shared caches such as CDNs and overridesmax-agefor them.Set-Cookieon a response is a common reason an otherwise cacheable page stays uncached. Check this on pages you expected to cache.
If caching is new to you, read CDN explained first for the general model.
Read cf-cache-status
Every response through Cloudflare should carry a cf-cache-status header. It is the single most useful debugging tool.
curl -sI https://example.com/assets/app.css | grep -iE "^(cf-cache-status|cache-control|age|etag|server)"
| Value | Meaning |
|---|---|
HIT | Served from Cloudflare's cache |
MISS | Cacheable, but not in cache at that data center; fetched from origin |
EXPIRED | Was cached, expired, refetched from origin |
REVALIDATED | Expired copy was checked with the origin and reused |
STALE or UPDATING | Served stale while a refresh happens |
BYPASS | Cache intentionally skipped, often due to origin headers or a rule |
DYNAMIC | Not eligible for caching, for example HTML under default rules |
Run the request twice. A first MISS followed by a HIT is normal. Because Cloudflare has many data centers, each location warms its own cache separately, so a MISS from a new region does not mean caching is broken. The age header shows how many seconds the object has been in cache. The HTTP Header Checker shows these headers without the command line.
Cache Rules
Cache Rules are the current way to control caching behavior, replacing most uses of the older Page Rules caching options. A rule has a matching expression (hostname, path, file extension, headers, cookies and more) and a set of actions.
Common settings:
- Cache eligibility: mark matching requests as eligible for cache or bypass the cache. Marking an HTML path "eligible" is how you cache full pages at the edge, similar to the old "Cache Everything" behavior.
- Edge TTL: how long Cloudflare keeps the object. You can respect the origin's headers, override them with a fixed duration, or set a duration only when the origin gives none.
- Browser TTL: the
max-ageCloudflare sends to visitors' browsers. You can respect the origin or override it. - Cache key adjustments: include or ignore query strings, cookies or headers when deciding whether two requests are the same object.
- Serve stale, and revalidation options where available.
Typical rule set for a content site:
- Bypass for admin and login paths, cart and checkout, and anything personalized. Expression idea: path starts with
/wp-admin,/wp-login.php,/cart,/checkout,/my-account, or the request carries a login cookie. - Eligible, long Edge TTL for static assets under
/wp-content/uploadsor/assets, using fingerprinted filenames so you can cache them for a long time. - Eligible, moderate Edge TTL for public HTML pages that are the same for every visitor, such as blog posts and marketing pages.
Order matters: rules are evaluated in sequence, so put bypass rules ahead of broad "cache everything" rules so personalized pages are never cached.
Choosing TTLs
Match the TTL to how the content changes and how you plan to invalidate it:
| Content | Suggested approach |
|---|---|
Fingerprinted assets (app.3f9a1c.js) | Very long TTL with immutable; the filename changes on deploy |
| Images and media | Long edge TTL; rename or purge on replacement |
| Blog and marketing HTML | Short to moderate edge TTL plus purge on publish |
| API responses | Usually bypass, unless public and safe to cache briefly |
| Personalized pages | Bypass |
Set these at the origin when you can. Origin headers travel with the file to every cache and browser. A pattern that works well is to send Cache-Control: public, max-age=31536000, immutable for fingerprinted assets, and Cache-Control: public, max-age=0, s-maxage=300 for HTML so browsers revalidate while the edge holds a copy for five minutes.
# nginx: long cache for fingerprinted assets
location ~* \.(?:css|js|woff2|png|jpg|webp|avif|svg)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
Do this only if your filenames change on every deploy. Otherwise visitors and the edge keep old versions for a year.
Purging the cache
Cloudflare's purge options, from broadest to most surgical (availability by plan may vary):
- Purge Everything: clears the whole zone. Every request becomes a
MISSuntil the cache refills, so your origin takes the full load. Use it rarely. - Purge by URL: clears exact URLs you list. The URL must match what Cloudflare stored, including scheme, hostname and query string.
- Purge by hostname, prefix, or tag: clears everything under a host, a path prefix, or objects labeled with a
Cache-Tagresponse header. Tags let a CMS purge "all pages mentioning product 42" in one call.
In the dashboard this lives under the Caching section, on the Configuration page, with a Purge Cache control. From the API:
# Purge specific URLs
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"files":["https://example.com/","https://example.com/pricing"]}'
# Purge everything
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"purge_everything":true}'
Use a scoped API token with only cache purge permission rather than a global key. Many CMS plugins and deployment pipelines can call this automatically on publish or release, which is better than manual clicking.
Remember that purging the edge does not clear visitors' browser caches. If you sent max-age=31536000 for a file, browsers hold it regardless of your purge. This is another reason to change filenames for assets rather than purge them.
Common problems
Changes don't appear after purge. Check the page's cf-cache-status and age. If age is high, the purge missed (wrong URL variant). Also check for a second cache in your stack, such as a WordPress caching plugin, server-level FastCGI cache, or hosting cache. Purge each layer from the origin outward.
Pages never cache. Look for Set-Cookie, Cache-Control: private or no-cache from the origin, a Vary header with high-cardinality values, or a bypass rule matching your path.
Logged-in users see stale or wrong content. Add a bypass condition on your login cookie names, and exclude account paths.
Query strings produce many copies. Marketing parameters like utm_source create separate cache entries unless you configure the cache key to ignore them.
Cache hit ratio is low. Fingerprint assets, remove unnecessary cookies on public pages, and consider Tiered Cache, which makes lower-tier data centers fetch from an upper-tier one rather than each hitting your origin. See origin shield in CDN explained.
Measure the effect
Compare time to first byte before and after enabling HTML caching with the वेबसाइट स्पीड टेस्ट and the advice in reduce time to first byte. The पेज वेट एनालाइज़र shows which assets are heaviest and therefore most worth caching well.
अगले कदम
- Inspect your cache headers with the HTTP Header Checker.
- Confirm Cloudflare is in front with the CDN डिटेक्टर.
- Review the setup basics in Cloudflare setup: DNS and SSL modes.
- Diagnose slow first byte with reduce time to first byte.
- Watch uptime while you experiment with the अपटाइम मॉनिटर.
सामान्य प्रश्न
Why is my HTML page showing cf-cache-status DYNAMIC?
Cloudflare does not cache HTML by default. Create a cache rule that marks the path eligible for cache, and ensure the origin does not send headers or cookies that prevent caching.
Is Purge Everything safe?
It is safe for correctness but expensive for performance, since every request goes to your origin until the cache refills. Prefer purging by URL, prefix or tag after content changes.
How long does a purge take?
Cloudflare designs purges to propagate quickly across its network, but check their documentation for current guidance. Verify with curl -I and the cf-cache-status and age headers.
Does purging clear the browser cache?
No. Browsers keep files for as long as the Cache-Control they received allows. Use versioned filenames for assets so a new URL bypasses old browser copies.
Get notified when this guide updates
Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.
यह पेज सामान्य जानकारी है, जिसे हमारी संपादकीय टीम ने लिखा है और दस्तावेज़ीकरण बदलने पर अपडेट किया जाता है। सर्वर और प्रदाता अलग-अलग होते हैं, इसलिए बदलाव पहले सुरक्षित तरीके से जाँचें। देखें: संपादकीय नीति और अस्वीकरण.