Guides

Performance guide

Cloudflare Cache Rules: A Safe Rollout Guide

Make public responses faster without turning a cache policy into a data-isolation incident.

Cloudflare caching is an application behavior, not just a performance switch. A correct rollout identifies which responses are public, defines the representation each request may receive, proves that the edge is serving the intended object, and provides a narrow way to remove it when content changes.

This guide is for DevOps and web engineers operating a proxied Cloudflare zone. Start with an asset or an explicitly public page. Do not use the first rollout to cache account pages, authenticated APIs, carts, checkout, search results personalized by identity, or any response that can contain one user's data.

Cache Everything is not a safety decision

A rule that makes broad dynamic traffic eligible for caching can cache private or personalized responses if its match and cache key do not preserve isolation. Exclude authenticated and stateful routes first; only make narrowly defined, demonstrably public responses eligible.

Prerequisites

  • A hostname whose DNS record is proxied through Cloudflare. Cache Rules apply to proxied traffic.
  • Access to the Cloudflare zone and to the origin configuration, plus a change record with a named owner and rollback time.
  • A staging hostname or a small, public production path that has no login, cookie-based variation, authorization, or user-specific output.
  • A representative test URL and a known expected response body, status, content type, and cache headers.
  • A deployment or content-publishing workflow that can purge the affected objects after a release.

Record a baseline before changing anything. The following command is safe for a public test object; inspect the response headers and save the result with the change record:

curl -sS -I https://www.example.com/assets/app.4d2c1.js

Look for the origin's Cache-Control intent and Cloudflare's CF-Cache-Status. A MISS on the first request is normal for a cold object. Run the same request again after the object has had an opportunity to populate the cache and confirm the status, response headers, and body are still appropriate. Do not treat one header from one edge location as proof for every route or region.

Keep four concerns separate

These controls solve different problems. Treating them as interchangeable is a common source of stale content and data exposure.

ConcernQuestion it answersPrimary control
Cache RulesWhich matching requests may be cached, bypassed, or given a different edge policy?A conditional Cloudflare rule
Cache keyWhich requests are the same cached representation?URL, selected query parameters, and only the safe variation dimensions
Origin cache headersIs this response public or private, and how should caches handle freshness and revalidation?The origin response's Cache-Control header
PurgeHow is an already stored representation removed after a change?A targeted invalidation workflow

Cloudflare documents Cache Rules as controls for cache eligibility, duration, and related cache settings. A cache key is the identifier used to store and retrieve a cached file; it is not an authorization boundary. Cloudflare's default key includes the full URL, including the query string, alongside other request properties. Changing it can consolidate distinct requests into one object, or split one object into many. Both outcomes must be intentional.

Origin headers remain the clearest expression of application intent. For example, Cache-Control: public, max-age=86400 communicates a public, cacheable response, while private tells shared caches not to store a response and no-store tells caches not to store it at all. Cloudflare can respect, augment, or override origin behavior depending on Cache Rule settings and Origin Cache Control; verify the resulting behavior rather than assuming the header alone wins.

Stage 1: classify routes before creating a rule

Build a small route table with the application owner. Include at least these categories:

Route typeInitial policy
Fingerprinted static assetsCandidate for long-lived public caching; a new filename provides versioned invalidation.
Public images, stylesheets, scripts, and fontsCandidate after checking query-string and content-variation behavior.
Public pages with stable outputCandidate for a short, explicit TTL and a tested purge path.
Login, account, cart, checkout, admin, and authenticated API routesBypass shared caching unless a separately reviewed design proves safe isolation.
Pages varying by session, entitlement, locale, experiment, inventory, or geolocationDo not share-cache until the exact variation and invalidation design is reviewed.

Check how the origin varies output. Vary is not automatically a complete Cloudflare cache-key design: Cloudflare documents specific support for configured Vary settings and particular cases. If a response changes because of a query parameter, header, cookie, or client characteristic, either include only the necessary safe dimension in the key or keep that response out of the shared cache. Never add an authorization token, session identifier, or other secret to a cache key as a shortcut; doing so creates a sensitive identifier in cache configuration and is rarely the right application design.

Stage 2: make the origin intent explicit

Prefer to make an asset or page's safety visible at the origin before adding an edge override. For a public immutable asset, use a response policy appropriate to the application's release model, such as:

Cache-Control: public, max-age=31536000, immutable

Only use a long lifetime when the URL changes whenever the bytes change. For a public HTML page that changes independently of its URL, choose a shorter lifetime and confirm that the publishing workflow can purge it. For sensitive pages, use a policy such as Cache-Control: no-store when the application requires that neither browser nor intermediary store the response; private is appropriate when browser caching is acceptable but shared caching is not.

s-maxage can set a shared-cache lifetime distinct from browser max-age. Cloudflare notes that it has revalidation implications, so do not combine directives by pattern matching. Test the exact combination your origin returns. The Cloudflare Origin Cache Control reference describes how no-cache, no-store, private, s-maxage, and stale directives interact with its cache behavior.

Stage 3: add one narrow Cache Rule

Create a rule that matches only the public test object or an equivalent, immutable asset namespace. Keep the first match simple: one hostname and one path prefix, with an explicit exclusion for any stateful or authenticated path that could overlap.

Make one decision per rollout:

  • Set cache eligibility only after the response is known to be public.
  • Set an edge TTL only when it is deliberately different from origin intent.
  • Change the cache key only when you can explain every representation that will be merged or split.

Avoid a broad "cache all HTML" policy. It commonly captures login-adjacent pages, application shells with user state, error responses, or routes that differ by cookie and authorization. If a future use case truly needs dynamic caching, design it with the application team: document the identity model, all variation inputs, origin headers, TTL, invalidation, and a test that proves one user cannot receive another user's response.

Cloudflare allows rules to be created through its dashboard, API, or Terraform. Use the delivery mechanism your team can review, version, and roll back. The authoritative Cache Rules documentation and rule examples are the source of current fields and capabilities.

Stage 4: verify cache behavior and content correctness

Warm and inspect the single public URL twice:

curl -sS -I https://www.example.com/assets/app.4d2c1.js
curl -sS -I https://www.example.com/assets/app.4d2c1.js

Then verify the object itself, not just its headers. Compare its checksum to the release artifact where possible:

curl -sS https://www.example.com/assets/app.4d2c1.js | shasum -a 256

Test every intended variation. For example, if a public image endpoint legitimately uses width and format query parameters, request each approved combination and confirm each response has the expected dimensions and type. Also request an irrelevant tracking parameter and confirm it behaves according to the chosen key policy. Do this only against non-sensitive public objects.

Use Cloudflare Trace to determine whether a Cache Rule and cache-key setting applied to a specific URL. Pair that result with origin request logs and application telemetry: a cache hit should reduce origin work without changing status, content type, security headers, or the response body. Measure cache hit ratio and origin load over a representative period, not just a successful single request.

Stage 5: publish with a targeted purge plan

Purging removes cached content; it does not decide whether a future request is eligible for caching. Keep it separate from rule design.

For a changed object, prefer the narrowest invalidation that matches the release: Cloudflare recommends single-file purge by URL, and also supports hostname, prefix, tag, cache-key-resource, and full-zone methods. A full purge is a last resort because it turns normal traffic into origin misses and can create avoidable load.

After a targeted purge, request the URL again and verify that the new representation reaches the edge, then repeat the header and checksum checks. If the cache key varies on a property relevant to the object, ensure the purge method covers the stored variants; Cloudflare documents the additional header, query-string, host, and prefix information required for some purge types.

Do not place a broadly privileged API token in a shell history, ticket, or CI log. Give the publishing system a least-privilege token, keep it in the secret store, and monitor failed or rate-limited purge requests. See Cloudflare's purge cache reference and purge by single-file guide for current API requirements and limits.

Rollback

  1. Disable or remove the most recent Cache Rule through the same reviewed configuration path used to deploy it.
  2. Restore the prior origin Cache-Control behavior if it changed with the rollout.
  3. Purge the narrowly affected URLs, prefixes, or tags so objects stored under the unsafe policy are not served until expiry.
  4. Re-run the public-object header and body checks, then test an authenticated or personalized journey that was deliberately excluded.
  5. Record the trigger, affected routes, cache statuses, purge scope, and follow-up action before attempting a broader rollout.

Common pitfalls and accuracy caveats

  • Using Cache Rules as an authorization mechanism: cache policy cannot replace application authorization. Keep private content out of a shared cache by default.
  • Dropping query strings without an inventory: ignoring all query strings can merge signed URLs, locale selectors, image transforms, pagination, and other distinct representations.
  • Assuming Vary solves all variation: validate the Cloudflare cache-key configuration and the request actually sent to origin.
  • Overriding origin headers without ownership: an edge TTL can hide fresh origin data or serve stale content longer than the product can tolerate.
  • Purging too broadly: a full purge can produce an origin thundering herd; use a narrow target and capacity checks first.
  • Treating documentation examples as a fixed interface: available settings, limits, and Origin Cache Control behavior can differ by plan and change over time. Confirm the current Cloudflare documentation and the behavior of the specific zone before deployment.

Authoritative references

Make edge caching safe to operate

Talk to Optimi about cache policy reviews, purge design, and origin protection for critical web properties.

Discuss cache architecture