Caching — Full Curriculum

Personal study reference, not customer-facing. Caching is the Cloudflare product every customer already has running and almost none of them fully understand — this covers what's actually cached by default, how to extend it, the real header precedence, and several corrections to commonly-repeated outdated claims (purge methods, Tiered Cache topology naming). Every fact below is sourced from live Cloudflare docs (full list at the bottom).

Module 1Fundamentals — default behavior & cf-cache-status

Caching is on for every customer right now, whether they've touched the settings or not — the gap is almost always that HTML and API responses aren't included by default, and people don't realize it.

What's cached automatically — by file extension, not MIME type

Cloudflare caches based on the URL's file extension only, never by the actual Content-Type the origin returns. HTML and JSON are not cached by default — this is the single most common gap customers hit. The default list covers image/video/audio/font/archive/document formats: 7Z, AVI, AVIF, APK, BIN, BMP, BZ2, CLASS, CSS, CSV, DOC, DOCX, DMG, EJS, EOT, EPS, EXE, FLAC, GIF, GZ, ICO, ISO, JAR, JPG, JPEG, JS, MID, MIDI, MKV, MP3, MP4, OGG, OTF, PDF, PICT, PLS, PNG, PPT, PPTX, PS, RAR, SVG, SVGZ, SWF, TAR, TIF, TIFF, TTF, WEBM, WEBP, WOFF, WOFF2, XLS, XLSX, ZIP, ZST. robots.txt is cached by default too, as a special case. Only GET and HEAD requests are ever cached — no exceptions.

Default Edge TTL — when no Cache-Control or Expires header is present

Status codeDefault TTL
200, 206, 301120 minutes
302, 30320 minutes
404, 4103 minutes
All other codesNot cached by default

The full cf-cache-status reference

ValueMeaning
HITServed from Cloudflare's cache
MISSNot in cache; Cloudflare fetched from origin and (usually) stored it
DYNAMICCloudflare decided before even checking the cache that this isn't eligible — see below
BYPASSWas eligible, but the origin response or a rule ultimately prevented storage — see below
EXPIREDWas cached, TTL ran out; will refresh from origin on this request
REVALIDATEDWas cached, TTL expired, origin confirmed via 304 it's still fresh
UPDATINGStale-while-revalidate: served from cache while an async refresh happens in the background
STALEOrigin is down — stale cache served anyway rather than an error
NONE/UnknownNot cached — usually a non-GET/HEAD method or a zero TTL

Not present at all on: 3xx redirects produced by Cloudflare itself (Redirect Rules, Bulk Redirects), WAF blocks, Cloudflare error pages, or Worker-originated fetch requests that don't go through the cache.

DYNAMIC vs. BYPASS — the distinction people blur together. DYNAMIC means Cloudflare decided "not eligible" before ever checking the cache — wrong file extension, a Bypass-cache rule matched, non-GET/HEAD method, or Development Mode is on (which suspends caching for 3 hours zone-wide). BYPASS means the request was eligible, but the actual response couldn't be stored — response exceeded the plan's max cacheable size, or the origin sent no-store/bare private. Critically: no-cache, max-age=0, and s-maxage=0 do NOT produce BYPASS — those produce MISS on the first request, then REVALIDATED or EXPIRED after. If a customer says "I set max-age=0 to stop caching," gently correct them: that still caches it, just marks it stale immediately. The directive that actually means "don't cache" is no-store.

Cache Deception Armor — a built-in protection most people don't know exists

When a response relies on heuristic freshness (no explicit Cache-Control), Cloudflare automatically runs Cache Deception Armor to defend against cache deception attacks. It only inspects responses whose Content-Type starts with text/ or application/ — the high-risk types for accidentally caching generated, user-specific content under a static-looking URL. If the request's file extension implies a MIME type (e.g. .css → text/css) that doesn't match the actual Content-Type returned, the response is refused caching and marked BYPASS. Setting any explicit Cache-Control directive skips this check entirely — it only activates when freshness is being guessed.

Module 2Cache Rules

The current, supported way to control caching — Page Rules are legacy, don't lead with them.

The three settings that matter

Custom Cache Key

Controls what Cloudflare treats as "the same request" for caching purposes. Can include or exclude: query strings (high-cardinality query params fragment the cache badly if not normalized), specific headers, cookies, device type, country (CF-IPCountry), or language (Accept-Language). Be deliberate about cardinality — adding too many variations to the cache key means near-zero hit rate since almost every request becomes "unique."

Bypassing cache for specific traffic

Common pattern for logged-in users on an otherwise-cacheable page: add a condition that bypasses when a session/auth cookie is present, e.g. AND cookie does not contain session_id. This lets the same URL serve cached content to anonymous visitors while always hitting origin for authenticated ones.

Module 3Cache-Control headers & precedence

The real, documented precedence — this gets mis-stated often, including in older internal material.

The actual precedence order is three tiers, not five: Cloudflare-CDN-Cache-Control > CDN-Cache-Control > Cache-Control. Within each of those headers, standard HTTP semantics apply (s-maxage for shared/CDN caches takes priority over plain max-age; the legacy Expires header is the lowest-priority fallback, used only when nothing else is present). An origin that returns Cache-Control: public, max-age=3600 together with CDN-Cache-Control: no-store produces BYPASS — the CDN-specific header wins even though the general one says cache it.

Origin Cache Control — plan-dependent default that trips people up

PlanOrigin Cache Control default
Free, Pro, BusinessEnabled by default
EnterpriseDisabled by default — must be turned on manually

When disabled, Cache-Control: no-cache, max-age=0, or s-maxage=0 from the origin don't produce the normal MISS→REVALIDATED/EXPIRED behavior — instead they're treated as no-store and the response isn't cached at all. If an Enterprise customer's cache-control headers seem to be "ignored," check this setting first.

A Cache Rule with "ignore cache-control header and use this TTL" overrides all of the above — origin headers become irrelevant for that matched traffic.

Module 4Tiered Cache

The free, single-highest-leverage toggle most customers haven't turned on. Solves a completely different problem than Cache Rules — Cache Rules reduce origin load on hits; Tiered Cache reduces origin load on misses.

The problem it solves

Cloudflare has 330+ data centers. Without Tiered Cache, every one of them can independently ask the origin for a cache miss — a brand-new or just-expired piece of content can trigger an origin stampede: dozens of data centers worldwide hitting the same origin for the same file simultaneously.

How it actually works

Data centers split into lower tiers (closest to visitors) and upper tiers (a small set closer to origin). A lower-tier miss asks an upper tier first, not the origin directly. Only upper tiers are permitted to contact origin at all. The practical effect: instead of 330+ data centers hammering origin, misses funnel through a handful of upper tiers — the first one fills the cache, everyone else pulls from it. Bonus: origin sees connections from a small, stable set of data centers instead of the whole network, reducing connection churn.

The four topologies

TopologyHow it picks the upper tierPlan
Smart (default)Dynamically selects the single closest upper tier per origin using real latency data — zero configurationAll plans, free
Generic GlobalConsistent-hash of the cache key into regional upper-tier pools; prioritizes regional locality and shared-cache efficiency over per-origin latencyAll plans, free
RegionalAdds a regional hub check before reaching an upper tier outside the region — for Smart/Custom topologies with upper tiers concentrated in one or two regionsEnterprise (bundled in Smart Shield Advanced)
CustomBespoke topology, configured with your account teamEnterprise

The public-cloud origin gotcha: origins on AWS, GCP, Azure, or Oracle Cloud use anycast/regional unicast networking that defeats Smart Tiered Cache's latency-probing — it can't tell where the origin actually is. Fix: set a cloud region hint (Caching → Tiered Cache → Origin Configuration, e.g. aws:us-east-1), which is free on every plan including Free. Without the hint, an anycast-fronted origin falls back to a less effective multi-upper-tier topology with lower hit rates. Also worth knowing: changing origin IPs/DNS while Smart Tiered Cache is active can reassign upper tiers and cause a temporary MISS spike while cache refills.

Check unicast vs. anycast before promising a region hint: region hints only help origins behind anycast. If the origin is on unicast (one fixed location), Smart Tiered Cache can already locate it through latency probing, and on Caching → Tiered Cache → Origin Configuration that origin shows a lock next to it with its assigned upper tiers (a primary plus a fallback). A locked origin can't take a region hint, and a hint wouldn't change anything. Before the call, open Origin Configuration: if you see the lock, skip the hint recommendation and focus on cache rules and cache keys instead. Only origins without the lock (anycast) are candidates for a hint.

Confirm Tiered Cache actually fired on a request via the CacheTieredFill field in Logpush http_requests logs. Separately: Workers have their own always-on, two-tier cache (lower tier near the eyeball, upper tier aggregating across the network) — this runs automatically for every Worker regardless of zone-level Tiered Cache settings, and isn't something you configure.

Module 5Smart Shield & Argo Smart Routing

Cloudflare now sells Tiered Cache, Connection Reuse, Argo, Regional Tiered Cache, and Cache Reserve as one bundled product — Smart Shield — rather than as separate standalone toggles. Argo in particular is commonly confused with caching; it isn't caching at all, and it's the one piece of this bundle that's genuinely a buying decision rather than a free win.

The three packages

PackageIncludesAvailability
Smart Shield (base)Smart Tiered Cache + Connection ReuseFree, Pro, Business, Enterprise — opt-in, no cost beyond plan
Smart Shield + ArgoBase package + Argo Smart RoutingFree, Pro, Business, Enterprise — purchasable self-serve
Smart Shield AdvancedBase + Argo + Regional Tiered Cache + Cache Reserve (+ Dedicated CDN Egress IPs)Enterprise only — not available for self-serve purchase on Free/Pro/Business, contact Enterprise Sales

Configured from Speed → Smart Shield in the dashboard (not the old standalone Caching menu) — select a package and follow the guided onboarding flow. Health Checks are available across all packages on Pro and above.

Connection Reuse — the other free win nobody mentions

Separate mechanism from Tiered Cache, bundled into every Smart Shield package including the base one. When upper-tier data centers need to reach your origin, Smart Shield batches multiple requests over a single shared TCP connection instead of opening a new one per request — this reduces total connections to origin by 30% on average. With HTTP/2, this extends into connection coalescing: requests for different hostnames can share one connection, as long as both resolve to the same IP/port and the origin's TLS certificate covers both hostnames in its SAN list.

Request collapsing — the correct term (not "coalescing")

When multiple requests hit the same Cloudflare data center simultaneously for the same uncached asset, Cloudflare uses a cache lock: only the first request is forwarded to origin, the rest wait and then have the response streamed to them once it arrives. This is called request collapsing in Cloudflare's own docs — you'll sometimes hear it called "request coalescing" informally, but that's not the documented product term. It's part of default cache behavior (not Smart-Shield-specific) and is explicitly scoped to a single data center in the documentation — don't claim it also compounds at the upper-tier layer unless/until that's separately confirmed.

Argo Smart Routing — what it actually is

Not caching. Argo optimizes the network path for traffic that has to reach your origin anyway — cache misses, dynamic pages, API calls, checkout flows, anything personalized. Without Argo, that traffic takes whatever path the public internet's BGP routing happens to choose that second, which can mean congestion or a suboptimal route. Argo continuously measures real-time latency and packet loss across paths and routes traffic over the fastest one available. Benefits are most apparent the farther your users are from your origin; built-in Analytics let you compare TTFB with Argo on vs. off.

Pricing correction: Argo used to be sold standalone with its own per-GB metered billing. That's no longer how it's offered — Argo is now exclusively accessed via the Smart Shield + Argo or Smart Shield Advanced packages. Don't quote old standalone per-GB pricing to a customer; point them to the Smart Shield package selector in the dashboard instead.

Qualifying sequence

  1. Is Smart Shield (base) turned on? It's free and bundles Smart Tiered Cache + Connection Reuse — there's no reason it should be off.
  2. Is a meaningful share of their traffic uncacheable — APIs, checkout, dynamic/personalized pages? If yes, that's the Argo conversation. If their traffic is mostly static and already well-cached, Argo has little to work with.
  3. Are their users geographically far from their origin? Argo's benefit scales with distance — a single-region domestic app sees a smaller gain than a global audience hitting one regional origin.
  4. Can they name a business KPI tied to TTFB — conversion rate, checkout abandonment, API SLA? If yes, Argo has a quantifiable business case. If not, it's a nice-to-have, not an urgent sell.

Do the free work first: confirm caching hygiene, then Smart Shield base. Only pitch Argo once there's real uncacheable, distance-sensitive traffic to justify it — customers who skip straight to a paid network-optimization add-on are sometimes just papering over content that should have been cacheable to begin with.

Module 6Cache Reserve

The ultimate upper-tier — persistent storage (built on R2) that holds content far longer than the standard cache would, specifically to shield origin from egress costs.

Eligibility requirements (all must be true)

Retention and purge behavior — a real cost trap

Starts at a 30-day retention period by default; an asset not requested within that window is evicted, and any request resets the clock. As of a September 2026 change, purging by tag, hostname, prefix, or "everything" now forces a Cache Reserve miss, not just a revalidation — the next request must pull the full content from origin again, and writing it back to Cache Reserve is billed as a Class A operation. Purge-by-URL already removed content outright and is unchanged. If a customer purges broadly and frequently, this is a real cost consideration worth flagging — a separate invalidate_cache endpoint exists specifically to revalidate instead of fully evict, which is the cheaper option when the goal is just "make sure this gets re-checked," not "force it to disappear immediately."

Usage-based pricing (storage + operations); requires a paid Cache Reserve plan, but you can keep using Cloudflare's regular CDN for free without it.

Module 7Purging

Correction to a commonly repeated claim: as of April 2025, all five purge methods are available on every plan, including Free — Purge Everything, Purge by Prefix, Purge by Hostname, Purge by URL (single-file), and Purge by Tag. This used to be Enterprise-only and some older internal material still says that; it's no longer accurate.

The five methods, roughly most-to-least surgical

MethodUse for
Purge by URLOne specific asset — the most precise option
Purge by TagGrouped invalidation via Cache-Tag response headers — cleanest for "everything related to this product/post changed"
Purge by PrefixEverything under a path, e.g. /static/
Purge by HostnameUseful for staging/preview deployments — up to 100 hostnames at once
Purge EverythingThe nuclear option

Purging by hostname (and similarly prefix/tag/everything) results in MISS on the next request normally — but with Tiered Cache enabled, it may instead show EXPIRED, since the lower tier tries to revalidate with the upper tier first rather than going straight to origin. All methods are available via API for CI/CD integration, not just the dashboard.

Module 8Workers & the Cache API

Reach for this when Cache Rules genuinely aren't expressive enough — not as a default approach.

From inside a Worker, the cf object on fetch() can override Cache Rules settings per-request: cacheEverything (treat as static regardless of extension), cacheTtl, cacheTtlByStatus (different TTLs per status-code range, e.g. {"200-299": 86400, 404: 1, "500-599": 0}), cacheKey (Enterprise only), and cacheTags for later targeted purging.

Workers also get a dedicated Cache API: ctx.cache.purge() (by tags, pathPrefixes, or purgeEverything — fields are unioned, not intersected, when combined) and an equivalent invalidate path. Note: pathPrefixes matches path starts only — no scheme/host/query — and is scoped to the calling entrypoint only; a purge from one Worker entrypoint won't affect cache stored by a different entrypoint even on overlapping paths. For exact-match-only semantics with zero over-purge risk, use a tag instead of a prefix.

Module 9APO, plans & decision framework

Automatic Platform Optimization (APO)

WordPress-specific, roughly $5/month add-on. Automatically caches HTML (the exact gap most customers have by default) and auto-purges on publish — no manual Cache Rule authoring required for the common WordPress case.

Decision framework — which tool for which scenario

ScenarioUse
Static assets (images, CSS, JS, fonts, video)Default cache — already on, no config
HTML pages, WordPressAPO
HTML pages, static site generator (Jekyll/Hugo/Astro)Cache Rule, long Edge TTL, purge on deploy
HTML pages, dynamic with logged-in usersCache Rule that bypasses on the auth/session cookie
Public API responsesCache Rules; Workers + Cache API if logic is too complex for a rule
Per-user API responsesWorkers KV — cache the underlying data, not the HTTP response itself
Large files, frequently accessedDefault cache + Tiered Cache
Large files, rarely accessed but must stay availableCache Reserve
Object storageR2 — zero egress fees
App state inside a WorkerKV (eventually consistent) or Durable Objects (strongly consistent)
Dynamic/uncacheable traffic (APIs, checkout, personalized), origin far from usersArgo Smart Routing (Smart Shield + Argo)
Origin getting too many simultaneous connections, not just too many requestsConnection Reuse (included in every Smart Shield package, incl. base)

Pricing gates, consolidated

FeaturePlan
Default cache, basic Cache Rules, Smart/Generic Global Tiered Cache, all 5 purge methodsAll plans, including Free
Smart Shield (base): Smart Tiered Cache + Connection ReuseAll plans, including Free — opt-in
Smart Shield + Argo (adds Argo Smart Routing)Self-serve purchase on Free, Pro, Business, Enterprise
APO for WordPress~$5/mo add-on
Custom Cache Keys, Cache by Cookie/HeaderPro and above
Cache ReserveUsage-based (storage + operations)
Smart Shield Advanced (Regional Tiered Cache + Cache Reserve bundled), Regional/Custom Tiered Cache standalone, non-standard caching ports, Origin Error Pass-through, Worker cacheKey override, Dedicated CDN Egress IPsEnterprise
R2Usage-based, zero egress fees

Module 10Live demo & test commands

Real curl commands showing DYNAMIC → MISS → HIT live, pulled from the companion demo script.

Before — confirm the gap exists

curl -sI https://nginx.tarheel.us/ | grep -iE "cf-cache|cf-ray|age"
// Expect: cf-cache-status: DYNAMIC — no file extension on "/", so it was never considered for caching

for i in 1 2 3; do curl -sI https://nginx.tarheel.us/ | grep cf-cache; done
// Three requests, three DYNAMICs, three round trips to origin

Configure — one Cache Rule (Module 2)

// Expression
(http.host eq "nginx.tarheel.us")
// Cache eligibility: Eligible for cache
// Edge TTL: Override origin -> 2 hours (any duration works for a demo)

After — watch it flip to HIT

for i in 1 2 3 4; do curl -sI https://nginx.tarheel.us/ | grep cf-cache; sleep 1; done
// cf-cache-status: MISS   <- first request, fetched from origin and stored
// cf-cache-status: HIT    <- served from the edge
// cf-cache-status: HIT
// cf-cache-status: HIT

One MISS populates the cache, everything after is a HIT — origin is no longer involved. At real traffic volume the ratio is far more dramatic than this small demo (often one MISS per thousand-plus HITs). For an extra visual, grep the age header too and watch it climb on repeated requests — that's edge time, not origin time.

Tiered Cache, live (Module 4)

Harder to demo with a single curl command since it requires multiple data centers to actually be hit, but the dashboard proof works well: after enabling Tiered Cache, check the CacheTieredFill field in Logpush http_requests logs to confirm it's actually engaging, and if the origin is on a public cloud, set the cloud region hint (Caching → Tiered Cache → Origin Configuration) in the same session so Smart Tiered Cache can actually locate it.

Argo Smart Routing, live (Module 5)

Argo is genuinely hard to demo with curl since the benefit is a network-path optimization you can't see client-side in a single request. Use the interactive visual demo instead — cf-demo-app.dustinburke23nc.workers.dev/argo shows a world map of traffic flowing from any region to a US-based origin, Argo on vs. off, with hop count, latency, and packet loss compared live. Pair it with the Analytics TTFB comparison (with Argo vs. without) for a customer's own domain once they've actually enabled a Smart Shield + Argo package.

The framing that lands with a CFO in the room: "every byte here is a byte your origin didn't have to send — if you're paying for egress on AWS or GCP, this is real money saved." Point at Cached Bandwidth in Analytics & Logs → Traffic (or Caching → Overview) specifically when that audience is present.

Module 11Rapid-fire Q&A

"My HTML isn't being cached — is something broken?"

No — HTML is never cached by default, regardless of plan. It's not a bug; URLs without a static file extension are assumed potentially personalized. Fix with a Cache Rule setting Cache Eligibility to "Eligible for cache," or APO if it's WordPress specifically.

"I set max-age=0 — why is it still showing as cached?"

max-age=0 means cached but immediately stale, not "don't cache." It'll show MISS then REVALIDATED/EXPIRED on subsequent requests, not BYPASS. If the goal is genuinely no caching at all, the origin needs to send no-store.

"Our origin is getting hammered — what's the fastest fix?"

Turn on Tiered Cache first — it's free, a single toggle, and specifically targets the origin-stampede problem that Cache Rules alone don't solve. Cache Reserve is the next step for content that's expensive to regenerate or accessed rarely but must stay available.

"Can we purge by cache tag on our plan?"

Yes, on any plan — this was Enterprise-only in the past but has been available to everyone since April 2025. Worth double-checking this against any older internal reference material that might still say otherwise.

"Should we cache by IP address for personalization?"

No — IPs are shared via CGNAT, corporate proxies, and NAT, so this leaks one user's cached content to another. Use a cookie, header, or Workers + KV instead.

"Page Rules or Cache Rules?"

Cache Rules — Page Rules are legacy. Don't lead a new configuration with Page Rules even though they still technically function.

Self-testQuiz

Click a question to reveal the answer. No peeking before you commit to one.

1. A customer requests "/" on their site and sees cf-cache-status: DYNAMIC. Is Cloudflare broken?

No — HTML and URLs without a static file extension are never cached by default on any plan. This is expected behavior, not a bug. Fix with a Cache Rule (Eligible for cache) or APO for WordPress.

2. True or false: setting Cache-Control: max-age=0 means the response won't be cached at all.

False. It's still cached, just immediately marked stale — you'll see MISS then REVALIDATED/EXPIRED on later requests, not BYPASS. The directive that actually prevents caching is no-store.

3. What's the real difference between DYNAMIC and BYPASS?

DYNAMIC means Cloudflare decided "not eligible" before ever checking the cache (wrong extension, non-GET/HEAD, Bypass rule, Dev Mode). BYPASS means the request was eligible, but the actual response couldn't be stored (too large, no-store/private from origin).

4. What's the actual Cache-Control header precedence order?

Cloudflare-CDN-Cache-Control > CDN-Cache-Control > Cache-Control — three tiers, not five. An origin can send a permissive Cache-Control but still get BYPASSed if CDN-Cache-Control: no-store is also present.

5. An Enterprise customer says their origin's cache-control headers are being "ignored." What's the first thing to check?

Whether Origin Cache Control is enabled — it's disabled by default on Enterprise (unlike Free/Pro/Business, where it's on by default). When disabled, directives like no-cache/max-age=0 get treated as no-store instead of the normal revalidation flow.

6. What problem does Tiered Cache solve that Cache Rules alone don't?

Origin load from cache misses. Without it, any of Cloudflare's 330+ data centers can independently hit origin on a miss, causing a stampede. Cache Rules only help with hits (serving from cache once something's there); Tiered Cache funnels misses through a small set of upper tiers instead.

7. A customer's origin is on AWS and Smart Tiered Cache doesn't seem to be picking a good upper tier. Why, and what's the fix?

AWS (and GCP/Azure/Oracle Cloud) use anycast/regional networking that defeats Smart Tiered Cache's latency-probing. Fix: set a cloud region hint (e.g. aws:us-east-1) — free on every plan including Free.

8. True or false: Regional and Custom Tiered Cache topologies are available on every plan, same as Smart and Generic Global.

False. Smart and Generic Global are free on all plans. Regional and Custom Tiered Cache are Enterprise-only (Regional is bundled into Smart Shield Advanced).

9. What are the four eligibility requirements for Cache Reserve?

Cacheable under standard rules, a freshness TTL of at least 10 hours, a Content-Length header present, and — for Image Transformations — only original files qualify, not resized variants.

10. A customer purges Cache Reserve content by tag frequently. What's the real cost implication?

Since a 2026 change, purging by tag/hostname/prefix/everything forces a full Cache Reserve miss (not just revalidation) — the next request pulls fully from origin and re-writes to Cache Reserve as a billed Class A operation. If the goal is just "re-check freshness," the invalidate_cache endpoint is the cheaper option instead.

11. True or false: Purge by Tag requires an Enterprise plan.

False — as of April 2025, all five purge methods (Everything, Prefix, Hostname, URL, Tag) are available on every plan including Free. This used to be Enterprise-only; some older material still incorrectly says it is.

12. What's the difference between the Workers cacheKey and cacheTags options in the cf object?

cacheKey changes what counts as "the same request" for caching purposes and is Enterprise only. cacheTags appends tags for later targeted purging and has no such plan restriction.

13. A customer wants to cache personalized content by client IP address. Good idea?

No. IPs are shared across many real users via CGNAT, corporate proxies, and NAT — caching by IP leaks one user's personalized content to another. Use a cookie, header, or Workers + KV instead.

14. Does Cloudflare cache POST requests?

No — only GET and HEAD methods are ever cached, with no exceptions in the standard cache. (Workers' Cache API can be used to intentionally cache non-standard scenarios, but that's a deliberate opt-in, not default behavior.)

15. What does Cache Deception Armor actually protect against, and when does it NOT activate?

It protects against cache deception attacks by checking that a URL's implied MIME type (from its file extension) matches the actual returned Content-Type, but only for text/* and application/* responses relying on heuristic freshness. Setting any explicit Cache-Control directive skips the check entirely.

16. A customer asks "does turning on Argo also turn on Tiered Cache, or are they separate purchases?"

Trick framing — you can't buy Argo standalone anymore. It only comes bundled: the Smart Shield + Argo package includes Smart Tiered Cache + Connection Reuse (the base package) plus Argo on top. There's no way to get Argo without also getting the base Smart Shield features.

17. True or false: "request coalescing" is the official Cloudflare term for what happens when simultaneous cache-miss requests hit the same data center.

False. The documented term is request collapsing, implemented via a cache lock — only the first request reaches origin, the rest wait and get the response streamed to them. "Coalescing" is sometimes used informally but isn't the term in Cloudflare's docs (and is easy to confuse with HTTP/2 connection coalescing, which is a different mechanism entirely).

Sources Cache responses (cf-cache-status reference) Default cache behavior Investigating uncached responses Cache Rules CDN-Cache-Control precedence Origin Cache Control Cache Deception Armor Tiered Cache Smart Shield overview Smart Shield packages & availability Argo Smart Routing (Smart Shield) Connection reuse Smart Tiered Cache Regional Tiered Cache Workers cache (always-on tiering) Cache Reserve Cache Reserve purge behavior change All purge methods available for all plans Purge by hostname Workers Cache API — purge and invalidate Workers cache debugging Troubleshooting slow websites / cache