Cloudflare Cache Hit Rate Stuck at 30%? These 3 Rules Will Boost It to 90%

Last month, I discovered my blog’s Cloudflare cache hit rate was stuck around 30%, and I was pretty frustrated. Despite using a CDN, images and CSS were cached fine, but HTML pages kept hitting the origin server, keeping it under constant load. After digging into it, I learned that Cloudflare doesn’t cache HTML by default! To make matters worse, the Page Rules configuration method I’d been using was marked as deprecated and would soon be phased out.
After two days of researching Cloudflare’s Cache Rules and Edge TTL configuration, I managed to boost the cache hit rate from 30% to 90%. My TTFB (Time To First Byte) dropped from 500ms to around 100ms, and server load decreased by 90%. To be honest, these results really surprised me.
In this article, I’ll walk you through configuring Cloudflare caching step by step—from understanding why HTML isn’t cached, to specific Cache Rules configuration steps, to verifying the results. If you’re also struggling with low cache hit rates, this should help.
Why Doesn’t Cloudflare Cache HTML by Default?
Cloudflare’s Default Caching Behavior
Let’s start with Cloudflare’s default caching strategy. By default, Cloudflare only caches static assets—images (JPG, PNG, GIF), stylesheets (CSS), and scripts (JS). HTML pages? Sorry, not cached by default.
Why is that? Cloudflare’s logic works like this: whether a resource can be cached depends on three main conditions:
- Cache-Control header: If it’s set to
private,no-store,no-cache, ormax-age=0, it won’t be cached - Response code: Only specific HTTP status codes will be cached (like 200, 301, 404, etc.)
- Request method: Only GET requests are cached, not POST, PUT, etc.
HTML pages are typically considered “dynamic content” that may contain user-specific information, so they’re not cached by default. This design actually makes sense—think about it, if your website has user login functionality, the HTML might contain usernames and personal information that shouldn’t be cached by a CDN and shown to other users.
The Real Reason HTML Isn’t Cached
Simply put, Cloudflare does this for security. I saw a post in the community forum about someone who enabled site-wide caching without thinking and ended up caching even the wp-login.php login page, along with login credentials. The consequences were predictable—any visitor could access the WordPress admin panel through the cached page. Pretty scary when you think about it.
That said, if your website is primarily static content, such as:
- Static blogs generated with Next.js, Gatsby, etc.
- Infrequently updated corporate websites or documentation sites
- Display-only product showcase pages
Then HTML caching can significantly improve performance. The key is configuring it correctly and excluding the pages that need to be excluded (admin panels, login pages, etc.).
How Much Improvement Can HTML Caching Bring?
I saw someone share their data on Medium: after configuring HTML caching, TTFB dropped from 500ms to the 100-160ms range, and server load decreased by 90%. That’s pretty dramatic.
Why such a big difference? It’s simple—before, every visitor to your site needed to fetch HTML from the origin server, which had to process requests, query databases, and render pages. Now? The CDN directly serves cached HTML to visitors, and the origin server doesn’t need to do anything. The higher your traffic, the more noticeable this difference becomes.
Page Rules is Deprecated—How to Migrate to Cache Rules?
The End of Page Rules
If you’ve used Cloudflare before, you probably know about Page Rules. This feature let us use the “Cache Everything” option to cache HTML. Unfortunately, Page Rules is now marked as deprecated.
Here’s the timeline:
- July 2024: Newly registered free accounts can no longer use Page Rules
- 2025: Cloudflare will automatically migrate existing Page Rules to the new system
- All new configurations must use Cache Rules going forward
Why deprecate it? It’s not hard to understand. Page Rules was old, not flexible enough in configuration, and the free tier only allowed 3 rules. For complex caching strategies, that’s really not enough.
The New World of Cache Rules
Cache Rules is Cloudflare’s newly launched caching configuration system, and it’s much more powerful. The biggest difference is:
Page Rules era: You had to manually select “Cache Everything” to cache all content
Cache Rules era: When you select “Eligible for cache,” the Cache Everything functionality is automatically enabled
This change is quite important. At first, I didn’t know this and kept looking for the “Cache Everything” option, only to discover it had been renamed.
Additionally, Cache Rules has more flexible matching conditions:
- Can match based on URI path, file extension, hostname, and more
- Supports regular expressions (though I rarely use them)
- Can combine multiple conditions
Migration Considerations
If you’re still using Page Rules, here are a few things to note:
Cloudflare will help you migrate: In 2025, Cloudflare will automatically convert your Page Rules to Cache Rules—you don’t need to do it manually (though you can migrate early if you want)
Some settings won’t be migrated: Specifically, the “Disable Security” and “Disable Performance” settings have been deprecated and won’t be migrated
Slight behavioral differences: Cache Rules’ “Eligible for cache” is equivalent to Page Rules’ “Cache Everything,” but the implementation logic has subtle differences
To be honest, I recommend starting to use Cache Rules now. You’ll have to switch eventually, so why not get it over with? Plus, Cache Rules is genuinely better and clearer to configure.
Cache Rules Configuration Practice: 3 Rules to Master Site-Wide Caching
Alright, enough theory—now let’s get practical. I’ll teach you how to configure 3 Cache Rules that cover everything from admin exclusion to full site caching.
Preparation: Access the Configuration Page
First, log into the Cloudflare console, select your domain, then:
- Click “Caching” in the left menu
- Find the “Cache Rules” tab
- Click the “Create rule” button
Now let’s configure them one by one.
Rule 1: Bypass Admin and Management Pages (Highest Priority)
Why put this first? Security first! This rule ensures your admin panels and login pages are never cached.
Configuration steps:
Rule name: Enter
Bypass Admin PagesWhen incoming requests match:
- Select “Custom filter expression”
- Field: select “URI Path”
- Operator: select “contains”
- Value: enter
/wp-admin(add more admin paths later if needed)
Add more exclusion paths: Click the “Or” button and continue adding:
/wp-login.php(WordPress login page)/admin/(generic admin path)/api/auth/(if you have API authentication endpoints)
Then:
- Cache eligibility: select “Bypass cache”
Priority: Set to 1 (highest priority)
Click “Deploy” when done. This rule ensures all requests containing these paths bypass caching and go straight to the origin.
Complete exclusion list for WordPress sites:
/wp-admin
/wp-login.php
/wp-json
/cart
/checkout
/my-accountAdjust this list based on your own website.
Rule 2: Cache Static Assets (Medium Priority)
This rule is actually optional since Cloudflare caches static assets by default. But configuring it explicitly gives you more precise TTL control.
Configuration steps:
Rule name:
Cache Static AssetsWhen incoming requests match:
- Field: select “File extension”
- Operator: select “is in”
- Value: enter
jpg png gif css js woff woff2 ttf svg ico(space-separated)
Then:
- Cache eligibility: select “Eligible for cache”
- Edge cache TTL: select “Use cache-control header if present, use default Cloudflare caching behavior if not”
Priority: Set to 2
This rule makes static assets prioritize the origin’s Cache-Control header, and if the origin doesn’t set it, use Cloudflare’s default TTL (typically 4 hours to 1 month, depending on file type).
Rule 3: Cache Everything Else (Lowest Priority)
Here’s the main event! This rule caches all other content, including HTML.
Configuration steps:
Rule name:
Cache Everything ElseWhen incoming requests match:
- Select “All incoming requests”
- Or, if you want more precision, select “Custom filter expression” and exclude specific paths
Then:
- Cache eligibility: select “Eligible for cache”
- Edge cache TTL: select “Ignore cache-control header and use this TTL”
- Duration: 7 days (1 week)
Priority: Set to 3 (lowest priority)
Why 1 week? It’s a balance. Too short (like 1 day) doesn’t show much caching benefit; too long (like 1 month) means content updates aren’t timely. For blogs and documentation sites that don’t update frequently, 1 week is a good choice.
Free tier note: Free accounts have a minimum TTL of 2 hours, Pro accounts 1 hour. If your content updates very frequently, you can set it shorter.
Rule Execution Order Matters
Cloudflare executes rules by priority from low to high:
- First executes Rule 1 (priority 1): Checks if it’s an admin page, bypasses if yes
- Then executes Rule 2 (priority 2): Checks if it’s a static asset, caches with appropriate TTL if yes
- Finally executes Rule 3 (priority 3): All remaining requests are cached for 1 week
This order ensures admin pages definitely won’t be cached, static assets use reasonable TTL, and HTML pages are force-cached for 1 week.
Complete Configuration Checklist
After configuring all three rules, check:
- Rule 1 has the highest priority (smallest number)
- All admin paths are added to the exclusion list
- Rule 3’s TTL is adjusted based on your update frequency
- All rules are deployed
Done! Now let’s talk about some Edge TTL pitfalls.
Edge TTL Configuration Details: Avoiding These Pitfalls
Edge TTL (Edge Cache Expiration Time) is the core of the entire caching strategy, but it’s also where errors happen most easily. I stepped into quite a few of these traps myself.
Understanding the Three Edge TTL Modes
Cloudflare’s Edge TTL has three modes, and choosing the right one is important:
Mode 1: Use cache-control header if present, bypass cache if not
- Translation: If there’s Cache-Control, follow it; if not, don’t cache
- Use case: Your origin server has comprehensive Cache-Control headers configured
- My take: Too strict. For many small sites, the origin doesn’t have Cache-Control configured at all, so this mode is equivalent to not caching
Mode 2: Use cache-control header if present, use default Cloudflare caching behavior if not (Recommended)
- Translation: If there’s Cache-Control, follow it; if not, use Cloudflare’s default rules
- Use case: Origin has some Cache-Control configured, and you want Cloudflare to intelligently handle the rest
- My take: The most balanced choice, suitable for most websites
Mode 3: Ignore cache-control header and use this TTL
- Translation: Regardless of what the origin says, force cache for the time I set
- Use case: Static websites, or when you clearly understand your caching strategy
- My take: Forceful but effective, suitable for full-site HTML caching scenarios
For HTML caching, I recommend Mode 3. Why? Many websites’ HTML pages don’t have Cache-Control set at all, or they’re set to no-cache (for security), in which case Modes 1 and 2 won’t cache. Mode 3 directly forces caching—simple and straightforward.
How to Choose TTL Duration?
This really varies by website. Here’s a reference table:
| Content Type | Recommended TTL | Reasoning |
|---|---|---|
| Static assets (images, CSS, JS) | 1 month | These files rarely change, long-term caching saves bandwidth |
| Blog article HTML | 1 week | Updates infrequent, 1 week is a good balance |
| Product page HTML | 1-3 days | Prices and inventory may change, can’t cache too long |
| Homepage HTML | 1 day | Homepage updates frequently, keep TTL shorter |
| API endpoints | Don’t cache or 5 minutes | Data timeliness requirements are high |
Remember the free tier limit: minimum 2 hours. If you find you can’t set it shorter, that’s the plan limitation.
My blog uses 1-week TTL. In practice, it works well—after publishing new articles, I manually Purge the cache (more on that later), and the cache hit rate stays super high the rest of the time.
Common Configuration Errors (I’ve Made Them All)
Error 1: Forgetting to Exclude Admin Pages
At first, I tried to save time and just created one “Cache Everything” rule. Result? The WordPress admin panel got cached too. When logging in, it kept showing old pages, and I had to manually clear the cache to see changes. Totally frustrating.
Solution: Always create the Bypass rule first, with the highest priority.
Error 2: TTL Too Long Causing Untimely Content Updates
Once I set TTL to 1 month and discovered I’d changed an article title, but visitors were still seeing the old title. It took me days to remember it was the cache’s fault.
Solution: Set TTL reasonably based on your update frequency. Update frequently, set it shorter; update rarely, set it longer. If unsure, try 1 week first.
Error 3: Confusing Edge TTL and Browser TTL
Edge TTL is the CDN node’s cache time; Browser TTL is the visitor’s browser cache time. They’re independent!
- Edge TTL: Controls how often Cloudflare’s CDN nodes fetch new content from origin
- Browser TTL: Controls how often visitors’ browsers request new content from the CDN
If you only set Edge TTL but not Browser TTL, visitor browsers will still frequently request from the CDN. Though the CDN won’t hit origin, the speed improvement for visitors is limited.
Solution: Browser TTL can be set to “Respect origin” or a reasonable value like 1 day.
Manual Cache Clearing: Purge Cache
What if content is updated? No need to wait for TTL expiration—you can manually clear the cache.
In the Cloudflare console:
- Go to “Caching” menu
- Find the “Purge Cache” area
- You can choose:
- Purge Everything: Clear entire site cache (simple and brutal)
- Custom Purge: Clear specific URL caches (precise)
I usually use Custom Purge, clearing only the few pages that were updated. Clearing the entire site causes all requests to hit origin for a short time, causing a sudden server load spike.
Pro tip: If you use WordPress, you can install a Cloudflare plugin that automatically purges relevant page caches when you publish articles—very convenient.
Verification and Optimization: Ensuring Cache Actually Works
After configuration, how do you know if it’s working? Don’t just guess—let’s use data.
Method 1: Browser Developer Tools
This is the simplest and most direct method.
- Open Chrome browser (or another browser)
- Press F12 to open developer tools
- Switch to the “Network” tab
- Visit your website homepage
- Find the HTML document in the Network list (usually the first request)
- Click it and view “Headers”
Focus on these headers:
cf-cache-status: This is key! Possible values:
- HIT: Cache hit! Content came from CDN, didn’t hit origin
- MISS: Cache miss, went to origin this time, but content will be cached
- DYNAMIC: Dynamic content, not cached (your Bypass rule might be working)
- BYPASS: Explicitly bypassing cache (should be admin pages)
- EXPIRED: Cache expired, CDN went to origin to update
First visit is usually MISS, second visit should become HIT. If it’s always DYNAMIC or BYPASS, something’s wrong with the configuration.
age: This header shows how long content has been cached on the CDN (in seconds). For example, age: 3600 means this content has been cached on the CDN for 1 hour.
cache-control: The origin’s cache strategy setting. Even if you used “Ignore cache-control” mode in Cloudflare, this header will still show, but Cloudflare won’t follow it.
Method 2: Verify with curl Command
If you’re comfortable with the command line, curl is more convenient:
curl -I https://your-website.comThe output will show all response headers. Look for cf-cache-status to see if it’s HIT or MISS.
Want more details? Use this:
curl -svo /dev/null https://your-website.com 2>&1 | grep -i "cf-cache"This will show only Cloudflare-related headers.
Method 3: Check Cache Metrics in Cloudflare Analytics
Want to see overall performance? Go to the Cloudflare console:
- Select your domain
- Click “Analytics” in the left menu
- Find the “Caching” tab
- View “Cache Hit Ratio”
Before configuration, my hit rate was 30%. The day after configuration, it jumped to 85%, and now it’s stable around 90%. If your hit rate has this kind of increase, configuration was successful.
Normal metric reference:
- Cache hit rate: Target 80%+
- Bandwidth savings: Should see obvious decrease (because lots of content doesn’t hit origin)
- Request count: CDN-served requests increase significantly, origin requests decrease significantly
Advanced Tips for Improving Cache Hit Rate
If hit rate still isn’t high enough, try these optimizations:
Tip 1: Warm the Cache
Newly published content’s first access is definitely MISS. If you want users’ first access to be HIT, you can “warm” it in advance:
After publishing new articles, visit all pages yourself first, letting the CDN cache the content. Or write a script to automatically crawl your site.
Tip 2: Unify URL Format
Same page, different URLs are treated as different cache objects:
https://example.com/pageandhttps://example.com/page?are differenthttps://example.com/pageandhttps://example.com/page/are different
Ensure your website link formats are consistent to avoid unnecessary cache MISSes.
Tip 3: Remove Useless Query Strings
If your URLs have tracking parameters (like ?utm_source=twitter), each parameter combination is treated as a different page, and cache hit rate will drop significantly.
Cloudflare has a “Query String Sort” feature that can be enabled in Caching settings. It sorts query parameters before caching, which can somewhat improve hit rate.
An even better approach is using Cloudflare’s Transform Rules to strip query parameters that don’t affect content.
Common Issue Troubleshooting
Issue 1: cf-cache-status Always Shows DYNAMIC
Possible causes:
- Origin’s Cache-Control is set to
no-cacheorprivate - Your Cache Rule didn’t match, request didn’t hit the “Eligible for cache” rule
Solution: Check Cache Rules matching conditions to ensure HTML requests are included. If using Mode 3 (Ignore cache-control), it should force cache.
Issue 2: Cache Hit Rate Only 50-60%, Not High Enough
Possible causes:
- Some pages’ URLs have dynamic parameters
- Origin’s certain headers are blocking caching
- CDN nodes are still gradually caching content (just configured, needs time)
Solution: Give the new configuration a couple days for CDN nodes to cache all content. Also check Analytics to see which types of requests have low hit rates and optimize accordingly.
Issue 3: After Updating Content, Visitors Still See Old Version
Possible cause: TTL set too long, or Browser Cache is also caching
Solution: Manually Purge Cache after publishing content. Or install an automation plugin (WordPress has many).
Summary
We’ve covered a lot—let’s review the core steps:
Understand why Cloudflare doesn’t cache HTML by default: Mainly security considerations, avoiding caching dynamic content and sensitive pages
Migrate from Page Rules to Cache Rules: Page Rules is being deprecated, Cache Rules is more powerful and flexible, “Eligible for cache” equals the old “Cache Everything”
Configure 3 Cache Rules:
- Rule 1 (priority 1): Bypass admin and login pages
- Rule 2 (priority 2): Cache static assets
- Rule 3 (priority 3): Force cache all other content (HTML), TTL recommended 1 week
Choose the right Edge TTL mode: For HTML, use “Ignore cache-control and use this TTL” to force cache, adjust duration based on update frequency
Verify results: Use browser developer tools to check
cf-cache-status, use Analytics to check cache hit rate, target 80%+
After I configured everything, my cache hit rate jumped from 30% to 90%, TTFB dropped from 500ms to around 100ms, and server load decreased by 90%. The effect is really obvious, especially for high-traffic websites.
Try it now:
- Check your current cache hit rate in Cloudflare Analytics
- Follow the article’s steps to configure 3 Cache Rules (remember to exclude admin first!)
- Wait a couple days, then check Analytics again
If you run into problems, check:
- Are admin pages being bypassed?
- Are Cache Rules priorities correct?
- Did you choose the right Edge TTL mode?
By the way, if you use WordPress, I strongly recommend installing the official Cloudflare plugin—it automatically clears cache when you publish articles, much more convenient.
Got questions or optimization tips? Feel free to share in the comments—let’s learn together!
Published on: Dec 1, 2025 · Modified on: Dec 4, 2025
Related Posts

Complete Guide to Deploying Astro on Cloudflare: SSR Configuration + 3x Speed Boost for China

Building an Astro Blog from Scratch: Complete Guide from Homepage to Deployment in 1 Hour
