Cache Rules
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 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:
| Position | Rule | Effect |
|---|---|---|
| 1 (top) | Bypass cache when path starts with /admin | Admin pages never cached |
| 2 | Cache Everything for path starts with /blog | Blog HTML pages cached |
| 3 | Edge TTL 1 year for path starts with /assets | Static 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
| Feature | Free Plan |
|---|---|
| Cache Rules | 10 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…)
| Field | Operator | Example |
|---|---|---|
URI Path | starts with, equals, contains, matches regex | /blog/, /assets/, /api/v1/ |
URI Query String | contains | ?preview=true |
Hostname | equals | static.example.com |
Cookie | contains | session_id |
Request Header | equals | X-Custom-Header: internal |
IP source address | in | 203.0.113.0/24 |
Country | in | US, DE, JP |
SSL | is on or off | HTTPS-only caching |
Conditions can be combined with AND / OR logic.
Actions (Then…)
| Action | What It Does |
|---|---|
| Bypass cache | Never cache — always fetch from origin |
| Eligible for cache | Enable caching for this request (required for HTML) |
| Edge TTL | Override how long the edge caches the response |
| Browser TTL | Override how long the browser caches the response |
| Cache Key | Customise what makes a unique cache entry (Pro+) |
| Serve Stale | Serve expired cache while revalidating (Pro+) |
| Respect origin headers | Let 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.
| Setting | Value |
|---|---|
| Rule name | Cache blog pages |
| When | URI Path starts with /blog |
| Cache eligibility | Eligible for cache |
| Edge TTL | Override — 1 hour (3600s) |
| Browser TTL | Override — 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.
| Setting | Value |
|---|---|
| Rule name | Bypass cache for logged-in users |
| When | Cookie contains session_id OR Cookie contains auth_token |
| Cache eligibility | Bypass cache |
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.
| Setting | Value |
|---|---|
| Rule name | Long cache for versioned assets |
| When | URI Path starts with /assets/ |
| Cache eligibility | Eligible for cache |
| Edge TTL | Override — 1 year (31536000s) |
| Browser TTL | Override — 1 year (31536000s) |
Because the filename itself changes with every deploy (e.g., app.a1b2c3.js → app.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.
| Setting | Value |
|---|---|
| Rule name | Cache public leaderboard |
| When | URI Path equals /api/v1/leaderboard |
| Cache eligibility | Eligible for cache |
| Edge TTL | Override — 60 seconds |
| Browser TTL | Override — 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.
| Setting | Value |
|---|---|
| Rule name | Bypass cache for staging |
| When | Hostname equals staging.example.com |
| Cache eligibility | Bypass cache |
Managing Rules via API
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets" \
-H "Authorization: Bearer $CF_TOKEN"
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:
| Aspect | Cache-Control Header (Origin) | Cache Rules (Cloudflare) |
|---|---|---|
| Where set | Your web server / application code | Cloudflare dashboard or API |
| Applies to | Both browser and CDN caches | Cloudflare edge only |
| Code change needed? | ✅ Yes | ❌ No |
| Granularity | Per-response | Per URL pattern / condition |
| Can override origin? | N/A | ✅ Yes — can ignore origin headers |
| Best for | Setting default behaviour | Exceptions 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
| Symptom | Likely Cause | Fix |
|---|---|---|
Status always DYNAMIC | Content type not cacheable, or Cache-Control: private from origin | Add a "Eligible for cache" Cache Rule, or fix origin headers |
Status always BYPASS | A rule or session cookie is bypassing | Check rule order; ensure bypass rule isn't matching too broadly |
Status HIT but content is stale | Edge TTL too long | Decrease Edge TTL or use targeted purge after deploy |
Status MISS on every request | Edge TTL too short, or different PoPs | Increase 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 This | Do This Instead |
|---|---|
| Bypass cache globally "to be safe" | Bypass only for authenticated/dynamic paths |
| Set Edge TTL shorter than 60 seconds | Use 60s minimum; for real-time data, don't cache at all |
Cache the /api/ root with a wildcard | Cache only specific public endpoints that are safe to share |
| Forget to bypass when cookies are present | Always add a Cookie contains session bypass rule |
| Set 1-year browser TTL on HTML pages | HTML 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-Controlheaders (from origin) and Cache Rules work together — rules can override origin headers.- Debug using the
cf-cache-statusresponse header.
What's Next
- Continue to Page Rules to understand the older rules system and how to migrate from it.