Skip to content
Back to Blog
Performance10 min read

Advanced Cloudflare Cache Rules: 8 Moves That Actually Work

Most Cloudflare setups only scratch the surface. These eight cache rule patterns unlock edge-case performance and prevent the subtle misses that waste origin bandwidth.

Written by Abdul AbrorTechnical Hosting Support Engineer
Advanced Cloudflare Cache Rules: 8 Moves That Actually Work
On this page

Why default cache rules leave bandwidth on the table

Most Cloudflare configurations stop after enabling Auto Minify and setting Browser Cache TTL. That covers maybe thirty percent of what the edge can handle. The rest—query string handling, conditional bypass, custom cache keys, stale content strategies—sits unused while your origin serves identical responses to a hundred edge requests.

I've seen WordPress sites cut origin load by seventy percent just by fixing how query parameters interact with cache. Not because the defaults are broken, but because they're safe and generic. These eight patterns handle the edge cases that burn bandwidth and slow time-to-first-byte.

1. Normalize query strings to collapse cache variants

Query parameters fragment your cache by default. ?utm_source=twitter and ?utm_source=facebook create two separate cache entries for identical content. Marketing tags, session IDs, and tracking parameters multiply cache misses while your origin regenerates the same page.

The fix is a Cache Rule that sorts query strings and strips irrelevant parameters before Cloudflare computes the cache key.

Create a rule matching your hostname, then set Cache Key > Query String > Include to only the parameters that actually change content—like page, id, lang, or category. Everything else gets ignored. For an API endpoint that accepts user_id and format but receives dozens of analytics parameters, your include list would contain just those two.

Rule: Cache key normalization
When: Hostname equals example.com AND URI Path starts with /api/
Then:
  Cache Key:
    Query String: Include only [user_id, format]

If you need the opposite—exclude specific parameters while keeping the rest—use the Ignore option and list tracking tags like utm_source, utm_medium, fbclid, gclid. For static assets that should never vary by query string at all, choose Ignore All.

This works because Cloudflare normalizes the cache key before checking its cache. Two requests that previously missed now hit the same cached object.

2. Cache authenticated requests with custom cache keys

Authenticated content usually bypasses cache entirely. A Cookie: session=xyz header tells Cloudflare to skip the edge and hit your origin every time. That's correct for account dashboards and checkout flows, but wasteful for personalized homepages or user-specific API responses that rarely change.

You can cache authenticated responses by customizing the cache key to include specific cookie values.

Set up a rule for the path you want to cache—say, /dashboard/overview—and configure Cache Key > Cookie to include only the cookie that identifies the user (often user_id or account_id). Strip session tokens and CSRF values. Cloudflare will now cache one response per user ID instead of bypassing cache entirely.

Rule: Cache per-user dashboard
When: URI Path equals /dashboard/overview
Then:
  Cache Key:
    Cookie: Include only [user_id]
  Edge Cache TTL: 5 minutes

Pair this with a short TTL—two to five minutes—so stale data doesn't linger. The origin still gets hit, just once per user per TTL window instead of on every request. For a thousand active users refreshing every ten seconds, that changes five thousand origin hits per minute into two hundred.

Be careful with privacy. Never cache responses that contain sensitive data for the wrong user. Test with multiple accounts and confirm cache keys are scoped correctly.

3. Serve stale content during origin outages

When your origin goes down, Cloudflare normally returns a 520 or 521 error. Visitors see downtime even though a cached copy of the page sat in the edge thirty seconds ago. The default behavior purges cache entries when they expire, so a five-minute TTL means five minutes of availability after origin failure.

The stale-if-error directive keeps expired content in cache as a fallback. If the origin returns a 500-series error, Cloudflare serves the stale cached version instead of propagating the failure.

Add a Cache Rule that sets Serve Stale Content to enabled. Cloudflare will retain cache entries beyond their TTL and serve them when the origin is unreachable.

Rule: Serve stale on error
When: Hostname equals example.com
Then:
  Serve Stale Content: Enabled

This doesn't extend the normal TTL—fresh requests still revalidate with the origin when it's healthy. But during an outage, visitors get slightly outdated content instead of an error page. Combine this with a longer Edge Cache TTL on static pages, and you can survive hours of origin downtime for public-facing content.

4. Bypass cache for specific HTTP methods while caching GET

By default, Cloudflare only caches GET and HEAD requests. That's fine until you have an API that uses GET for reads and POST for writes, and you want to cache the reads but never the writes. Most setups either enable caching everywhere (and accidentally cache POST responses) or disable it entirely (and lose the benefit for GET).

Cache Rules let you specify method-based conditions.

Create one rule that caches GET and HEAD requests for your API path, and another that explicitly bypasses cache for POST, PUT, PATCH, DELETE on the same path.

Rule 1: Cache API reads
When: URI Path starts with /api/ AND HTTP Method in [GET, HEAD]
Then:
  Cache Eligibility: Eligible
  Edge Cache TTL: 60 seconds

Rule 2: Bypass API writes
When: URI Path starts with /api/ AND HTTP Method in [POST, PUT, PATCH, DELETE]
Then:
  Cache Eligibility: Bypass cache

Order matters. Place the bypass rule above the cache rule so writes are evaluated first. Otherwise, a POST request might match the broader path condition and get cached.

This pattern is common for REST APIs where read endpoints handle ninety percent of traffic but write endpoints must always hit the origin.

5. Set different TTLs by content type or URI pattern

A single site often contains content with wildly different staleness tolerances. CSS and JavaScript can be cached for a month. HTML pages should revalidate every few minutes. API responses might be safe for thirty seconds.

Instead of one global TTL, create multiple Cache Rules that match specific patterns and assign appropriate lifetimes.

For static assets, match file extensions:

Rule: Cache static assets long-term
When: File extension in [css, js, woff2, jpg, png, webp]
Then:
  Edge Cache TTL: 30 days
  Browser Cache TTL: 7 days

For dynamic pages:

Rule: Cache HTML short-term
When: File extension equals html OR URI Path equals /
Then:
  Edge Cache TTL: 5 minutes
  Browser Cache TTL: 0 seconds

For APIs, match the path prefix and set a TTL appropriate to update frequency:

Rule: Cache API responses briefly
When: URI Path starts with /api/posts
Then:
  Edge Cache TTL: 60 seconds

This tiered approach maximizes cache hit ratio without serving stale critical content. Static assets stay cached across deployments, while dynamic content revalidates frequently.

6. Use origin Cache-Control headers selectively

By default, Cloudflare respects Cache-Control headers from your origin. If your application sets Cache-Control: no-cache, the edge won't cache it no matter what your Cache Rules say. That's a problem when legacy code or third-party libraries emit overly cautious headers.

You can override origin headers with the Origin Cache Control setting in Cache Rules. Set it to off, and Cloudflare ignores Cache-Control, Expires, and Pragma directives from your origin.

Rule: Ignore origin cache headers for static assets
When: File extension in [css, js, jpg, png]
Then:
  Origin Cache Control: Off
  Edge Cache TTL: 30 days

Now even if your origin responds with Cache-Control: no-store, Cloudflare caches the file for thirty days.

Use this carefully. If your origin explicitly says not to cache something, there's usually a reason—personalized content, CSRF tokens, or session data. Override headers only for paths you've verified are safe to cache.

For dynamic content where you do want to respect origin headers but adjust the TTL, leave Origin Cache Control on and set a shorter Edge Cache TTL as a ceiling.

7. Cache responses with query strings only for allowlisted paths

Cloudflare's default behavior caches URLs with query strings, but many applications append random parameters that prevent cache hits. A blog with ?share=twitter appended to every link sees a new cache entry for every social share, even though the content is identical.

You already normalized query strings in move one, but sometimes you want to cache only specific paths with query strings and bypass everything else.

Set up a rule that caches query string URLs only for paths like /search or /filter where parameters are semantic, and another rule that bypasses cache for all other query string requests.

Rule 1: Cache search and filter pages
When: URI Path in [/search, /products] AND URI Query String is not empty
Then:
  Cache Eligibility: Eligible
  Cache Key: Include [q, category, sort]

Rule 2: Bypass cache for other query strings
When: URI Query String is not empty
Then:
  Cache Eligibility: Bypass cache

Place rule one above rule two. Requests to /search?q=hosting get cached, while /blog/post?utm_source=email bypasses.

This prevents tracking parameters from polluting cache on pages where they don't matter, while still caching pages where query strings carry meaning.

8. Prefetch and cache third-party resources on your domain

External resources—fonts from Google, scripts from CDNs, analytics pixels—force browsers to perform DNS lookups, TLS handshakes, and HTTP requests to multiple origins. Each one adds latency, especially on mobile networks.

You can proxy third-party resources through Cloudflare by creating Cache Rules that fetch from the external origin and serve the response as if it came from your domain.

Set up a Worker or a Cache Rule that matches a path like /cdn-proxy/ and configures the Origin Override to point at the third-party domain.

Rule: Proxy Google Fonts
When: URI Path starts with /fonts/google/
Then:
  Origin Server: fonts.googleapis.com
  Host Header: fonts.googleapis.com
  Edge Cache TTL: 30 days

Now your HTML references /fonts/google/roboto.woff2 instead of the Google Fonts URL. Browsers make one fewer connection, and Cloudflare caches the font on the edge just like your own assets.

This works for any cacheable third-party resource—JavaScript libraries, icon fonts, public images. Just make sure the resource licensing allows proxying, and respect cache headers to avoid serving outdated content.

What happens when rules conflict?

Rule order determines which configuration applies. Cloudflare evaluates Cache Rules from top to bottom and stops at the first match. If rule three matches your request, rules four through ten never run.

Most conflicts come from overlapping path or hostname conditions. A rule for /api/* and another for /api/public/* will both match /api/public/status, but only the higher one executes.

Sort rules from most specific to least specific. Put exact path matches at the top, prefix matches in the middle, and broad hostname rules at the bottom. For method-based bypass rules, place them above caching rules so writes are never accidentally cached.

If a rule isn't behaving as expected, check the order first. Cache analytics will show which rule matched each request.

Testing rule behavior without breaking production

Before rolling out a new Cache Rule, test it with a staging hostname or a ?debug=1 query parameter that only you use. Set the rule condition to match Hostname equals staging.example.com or URI Query String contains debug=1, then send test requests and inspect response headers.

Cloudflare adds CF-Cache-Status to every response. The values you'll see:

  • HIT — served from cache
  • MISS — not in cache, fetched from origin, now cached
  • EXPIRED — was cached but TTL expired, revalidated
  • BYPASS — cache explicitly bypassed by rule
  • DYNAMIC — content not cacheable

If you expected HIT but see BYPASS, check your Cache Eligibility setting and any origin headers that might be overriding it. If you see DYNAMIC, the origin likely sent Cache-Control: no-cache and you haven't disabled Origin Cache Control.

Once behavior matches expectations on staging, update the hostname condition to production.

Frequently asked questions

Do Cache Rules apply to both Free and Pro plans?
Cache Rules are available on Pro, Business, and Enterprise plans. Free plans use legacy Page Rules with similar but more limited functionality.

Can I cache POST requests?
Technically yes, but it's almost never correct. POST responses are usually dynamic and should hit the origin. If you have a read-only API that uses POST for large query bodies, consider switching to GET with a request body or using a Worker to convert it.

What happens if I set Edge Cache TTL longer than Browser Cache TTL?
The edge caches for the longer duration, but the browser revalidates sooner. A resource with Edge TTL of one day and Browser TTL of one hour will stay cached at Cloudflare for twenty-four hours, but browsers will check for updates every hour. This is common for HTML pages.

Can I cache responses that set cookies?
Yes, but be careful. If the response sets a user-specific session cookie, caching it means every visitor gets the same cookie. Only cache responses with Set-Cookie if the cookie is not user-specific—like a static tracking or consent cookie.

How do I purge cache for a specific rule?
Purge by URL, prefix, tag, or hostname. Cache Rules don't have per-rule purge options, but you can tag responses with Cache-Tag headers and purge by tag to clear related content.

Where cache rules deliver the biggest wins

These patterns matter most when your origin is slow, expensive, or far from your users. A WordPress site on shared hosting with two-second response times will see dramatic improvements from aggressive edge caching. An API that queries a database for every request can offload ninety percent of reads to the edge with well-tuned TTLs and cache keys.

Start with query string normalization and method-based bypass—those two catch the majority of wasted cache opportunities. Add stale content serving for resilience, then dial in TTLs by content type. The remaining patterns handle edge cases that become visible once basic caching is working.

Cache analytics will show your hit ratio climbing from thirty or forty percent to seventy or eighty as you refine rules. Each ten-point increase means thousands fewer origin requests.