Skip to main content

Cache Rules

Learning Focus

By the end of this lesson you will understand how Cache Rules work, how they differ from setting Cache-Control on your origin, how to build rules for the most common use cases, and what the free-tier limits are.

What Are Cache Rules?

Cache Rules are the modern Cloudflare mechanism for controlling exactly how and when content is cached at the edge. They let you override the default caching behaviour — per URL path, cookie, header, query string, country, or any combination — without changing a single line of code on your origin server.

Think of Cache Rules as a policy engine that runs on every incoming request before it reaches your origin. The rule matches a condition, then applies a caching action.

flowchart LR
REQ["Incoming Request"] --> ENGINE["Cache Rules Engine\n(evaluate top to bottom)"]
ENGINE -->|"Rule 1 matched"| ACTION1["Bypass Cache\n(admin paths)"]
ENGINE -->|"Rule 2 matched"| ACTION2["Edge TTL: 1 day\n(static assets)"]
ENGINE -->|"Rule 3 matched"| ACTION3["Cache Everything\n(blog pages)"]
ENGINE -->|"No match"| DEFAULT["Default Behaviour\n(static extensions only)"]

style ENGINE fill:#f6821f,color:#fff,stroke:#e5711e
style ACTION1 fill:#dc2626,color:#fff,stroke:#b91c1c
style ACTION2 fill:#16a34a,color:#fff,stroke:#15803d
style ACTION3 fill:#2563eb,color:#fff,stroke:#1e40af
Cache Rules vs Page Rules

Cache Rules are the replacement for Page Rules for all cache-related settings. Cloudflare officially recommends migrating to Cache Rules. Page Rules still work but are no longer receiving new features. See the Page Rules lesson for migration guidance.

How the Rules Engine Evaluates Rules

Cache Rules are evaluated in order, top to bottom. The first rule that matches a request wins and its action is applied. Rules below it are skipped.

This means rule ordering matters:

PositionRuleEffect
1 (top)Bypass cache when path starts with /adminAdmin pages never cached
2Cache Everything for path starts with /blogBlog HTML pages cached
3Edge TTL 1 year for path starts with /assetsStatic assets cached long
4 (bottom)(fallback)Everything else: default behaviour

If /admin/dashboard is requested — Rule 1 matches → stop. Rules 2, 3, 4 are never reached.

Free Tier Limits

FeatureFree Plan
Cache Rules10 rules
Edge TTL control
Browser TTL override
Bypass cache
Cache Everything
Custom Cache Keys❌ (Pro+)
Serve Stale❌ (Pro+)

The Rule Builder — Fields and Actions

Conditions (When…)

FieldOperatorExample
URI Pathstarts with, equals, contains, matches regex/blog/, /assets/, /api/v1/
URI Query Stringcontains?preview=true
Hostnameequalsstatic.example.com
Cookiecontainssession_id
Request HeaderequalsX-Custom-Header: internal
IP source addressin203.0.113.0/24
CountryinUS, DE, JP
SSLis on or offHTTPS-only caching

Conditions can be combined with AND / OR logic.

Actions (Then…)

ActionWhat It Does
Bypass cacheNever cache — always fetch from origin
Eligible for cacheEnable caching for this request (required for HTML)
Edge TTLOverride how long the edge caches the response
Browser TTLOverride how long the browser caches the response
Cache KeyCustomise what makes a unique cache entry (Pro+)
Serve StaleServe expired cache while revalidating (Pro+)
Respect origin headersLet origin Cache-Control decide (default)

Building Cache Rules — Step by Step

Navigate to Cloudflare Dashboard → your domain → Caching → Cache Rules → Create rule.

Rule 1: Cache HTML Blog Pages

Problem: By default, Cloudflare does not cache HTML. Your /blog pages are static and change only when you publish — but every visitor hits your origin.

SettingValue
Rule nameCache blog pages
WhenURI Path starts with /blog
Cache eligibilityEligible for cache
Edge TTLOverride — 1 hour (3600s)
Browser TTLOverride — 5 minutes (300s)

Why 5 min browser / 1 hr edge? The browser re-checks in 5 min (so you can push a cache purge and users get fresh articles quickly). The edge holds the response for 1 hour — your origin only gets called once per hour per PoP.

Rule 2: Bypass Cache for Authenticated Sessions

Problem: Logged-in users see personalised content. If their page gets cached, another user might receive their data.

SettingValue
Rule nameBypass cache for logged-in users
WhenCookie contains session_id OR Cookie contains auth_token
Cache eligibilityBypass cache
Security-Critical

This rule is not optional — it is a security requirement. Caching personalised or authenticated pages is a data leakage vulnerability. Always bypass for any request that carries a session or auth cookie.

Rule 3: Long-Duration Cache for Versioned Static Assets

Problem: Your /assets/ directory contains files with content-hashed names (app.a1b2c3.js). The hash changes when the file updates. You want the CDN to hold these forever.

SettingValue
Rule nameLong cache for versioned assets
WhenURI Path starts with /assets/
Cache eligibilityEligible for cache
Edge TTLOverride — 1 year (31536000s)
Browser TTLOverride — 1 year (31536000s)

Because the filename itself changes with every deploy (e.g., app.a1b2c3.jsapp.d4e5f6.js), there is no stale content risk.

Rule 4: Cache an API Endpoint for a Short Period

Problem: /api/v1/leaderboard returns data that changes every 60 seconds. Without caching, thousands of users trigger thousands of database queries.

SettingValue
Rule nameCache public leaderboard
WhenURI Path equals /api/v1/leaderboard
Cache eligibilityEligible for cache
Edge TTLOverride — 60 seconds
Browser TTLOverride — 10 seconds

Result: The leaderboard is fetched from your database at most once every 60 seconds per PoP — regardless of whether 10 or 10,000 users request it simultaneously.

Rule 5: Bypass Cache in Development Mode

Problem: During local testing with a staging vhost, you want to ensure no stale content from your staging runs.

SettingValue
Rule nameBypass cache for staging
WhenHostname equals staging.example.com
Cache eligibilityBypass cache

Managing Rules via API

List all Cache Rules for a zone
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets" \
-H "Authorization: Bearer $CF_TOKEN"
Create a Cache Rule via API
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_request_cache_settings/entrypoint/rules" \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"description": "Cache blog pages for 1 hour",
"expression": "starts_with(http.request.uri.path, \"/blog\")",
"action": "set_cache_settings",
"action_parameters": {
"cache": true,
"edge_ttl": {
"mode": "override_origin",
"default": 3600
},
"browser_ttl": {
"mode": "override_origin",
"default": 300
}
}
}'

Cache Rules vs Cache-Control Headers

Both control caching — but they work at different layers:

AspectCache-Control Header (Origin)Cache Rules (Cloudflare)
Where setYour web server / application codeCloudflare dashboard or API
Applies toBoth browser and CDN cachesCloudflare edge only
Code change needed?✅ Yes❌ No
GranularityPer-responsePer URL pattern / condition
Can override origin?N/A✅ Yes — can ignore origin headers
Best forSetting default behaviourExceptions and overrides

Best practice: Set sensible Cache-Control headers on your origin for all content types, then use Cache Rules to handle the exceptions (bypass for auth, long TTL for assets, cache-everything for blog posts).

Debugging Cache Rules

Check cf-cache-status

curl -sI https://example.com/blog/my-article | grep cf-cache-status
# cf-cache-status: HIT ← served from cache ✅
# cf-cache-status: MISS ← fetched from origin (first request)
# cf-cache-status: BYPASS ← a rule or header bypassed the cache
# cf-cache-status: DYNAMIC ← Cloudflare treated as uncacheable

Common Debugging Questions

SymptomLikely CauseFix
Status always DYNAMICContent type not cacheable, or Cache-Control: private from originAdd a "Eligible for cache" Cache Rule, or fix origin headers
Status always BYPASSA rule or session cookie is bypassingCheck rule order; ensure bypass rule isn't matching too broadly
Status HIT but content is staleEdge TTL too longDecrease Edge TTL or use targeted purge after deploy
Status MISS on every requestEdge TTL too short, or different PoPsIncrease Edge TTL; first request to each PoP will always be a MISS

Common Misconceptions

"Cache Rules make pages public"

Reality: Cache Rules just tell Cloudflare whether to cache — they do not change your application's authentication logic. Users still need to log in; Cloudflare just serves the response from cache instead of hitting your server every time. However, you must bypass cache for pages that contain personalised content.

"I need to keep adding rules for every new page"

Reality: Use path prefixes (/blog/, /assets/) instead of specific URLs. One rule covering /blog/ caches every blog post — present and future.

"More Cache Rules means more overhead per request"

Reality: The Cloudflare Ruleset Engine evaluates rules extremely quickly (sub-millisecond). Ten rules add negligible processing time.

Anti-Patterns to Avoid

Don't Do ThisDo This Instead
Bypass cache globally "to be safe"Bypass only for authenticated/dynamic paths
Set Edge TTL shorter than 60 secondsUse 60s minimum; for real-time data, don't cache at all
Cache the /api/ root with a wildcardCache only specific public endpoints that are safe to share
Forget to bypass when cookies are presentAlways add a Cookie contains session bypass rule
Set 1-year browser TTL on HTML pagesHTML should have short browser TTL so you can push updates

Key Takeaways

  • Cache Rules are the modern replacement for Page Rules for all caching configuration.
  • Rules run in order — top-to-bottom; place more-specific rules above broader ones.
  • Free tier gives you 10 rules — more than enough for most sites.
  • Always bypass cache for sessions/auth cookies — this is a security requirement.
  • Use path prefixes to write rules that cover entire sections of your site with one rule.
  • Cache-Control headers (from origin) and Cache Rules work together — rules can override origin headers.
  • Debug using the cf-cache-status response header.

What's Next

  • Continue to Page Rules to understand the older rules system and how to migrate from it.