BetterLink Logo BetterLink Blog
Switch Language
Toggle Theme

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

Cloudflare Cache Rules configuration diagram showing cache hit rate improvement from 30% 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:

  1. Cache-Control header: If it’s set to private, no-store, no-cache, or max-age=0, it won’t be cached
  2. Response code: Only specific HTTP status codes will be cached (like 200, 301, 404, etc.)
  3. 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:

  1. 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)

  2. Some settings won’t be migrated: Specifically, the “Disable Security” and “Disable Performance” settings have been deprecated and won’t be migrated

  3. 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:

  1. Click “Caching” in the left menu
  2. Find the “Cache Rules” tab
  3. 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:

  1. Rule name: Enter Bypass Admin Pages

  2. When 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)
  3. 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)
  4. Then:

    • Cache eligibility: select “Bypass cache”
  5. 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-account

Adjust 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:

  1. Rule name: Cache Static Assets

  2. When 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)
  3. Then:

    • Cache eligibility: select “Eligible for cache”
    • Edge cache TTL: select “Use cache-control header if present, use default Cloudflare caching behavior if not”
  4. 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:

  1. Rule name: Cache Everything Else

  2. When incoming requests match:

    • Select “All incoming requests”
    • Or, if you want more precision, select “Custom filter expression” and exclude specific paths
  3. Then:

    • Cache eligibility: select “Eligible for cache”
    • Edge cache TTL: select “Ignore cache-control header and use this TTL”
    • Duration: 7 days (1 week)
  4. 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:

  1. First executes Rule 1 (priority 1): Checks if it’s an admin page, bypasses if yes
  2. Then executes Rule 2 (priority 2): Checks if it’s a static asset, caches with appropriate TTL if yes
  3. 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 TypeRecommended TTLReasoning
Static assets (images, CSS, JS)1 monthThese files rarely change, long-term caching saves bandwidth
Blog article HTML1 weekUpdates infrequent, 1 week is a good balance
Product page HTML1-3 daysPrices and inventory may change, can’t cache too long
Homepage HTML1 dayHomepage updates frequently, keep TTL shorter
API endpointsDon’t cache or 5 minutesData 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:

  1. Go to “Caching” menu
  2. Find the “Purge Cache” area
  3. 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.

  1. Open Chrome browser (or another browser)
  2. Press F12 to open developer tools
  3. Switch to the “Network” tab
  4. Visit your website homepage
  5. Find the HTML document in the Network list (usually the first request)
  6. 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.com

The 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:

  1. Select your domain
  2. Click “Analytics” in the left menu
  3. Find the “Caching” tab
  4. 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/page and https://example.com/page? are different
  • https://example.com/page and https://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-cache or private
  • 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:

  1. Understand why Cloudflare doesn’t cache HTML by default: Mainly security considerations, avoiding caching dynamic content and sensitive pages

  2. 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”

  3. 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
  4. 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

  5. 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:

  1. Check your current cache hit rate in Cloudflare Analytics
  2. Follow the article’s steps to configure 3 Cache Rules (remember to exclude admin first!)
  3. 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