Skip to main content

Cache Reserve

Learning Focus

By the end of this lesson you will understand what cache eviction is, why it forces your origin to serve more traffic than expected, how Cache Reserve eliminates this using R2, and when it is worth enabling on your zone.

Paid Feature

Cache Reserve is available on the Paid plans only (Pro, Business, Enterprise). It is billed based on the volume of data stored in R2 and the number of Class A and Class B R2 operations. There is no free tier for Cache Reserve itself.

This lesson explains how it works and when to consider it, since understanding the problem it solves is valuable even on the free plan.

The Problem: Cache Eviction

Cloudflare's edge caches are in-memory — fast, but finite in size. When a PoP's cache fills up, it must discard (evict) older or less-popular entries to make room for new content. This is called cache eviction.

Your e-commerce site has 80,000 product images. Your top 100 products get thousands of views per day — they stay in cache. But the other 79,900 products might receive only 1–5 views per week each. At that frequency, their images are evicted from every PoP between requests. Every view is a cache MISS — and a direct call back to your origin.

This is the long-tail eviction problem: content that is valid (not expired) but infrequent keeps getting thrown out of the in-memory cache and generates unnecessary origin load.

flowchart TD
subgraph NoCR["Without Cache Reserve"]
A_USER["User requests\nrare product image"] --> A_POP["Edge PoP"]
A_POP -->|"Not in memory\n(evicted by popular content)"| A_ORIGIN["Origin Server\n⚠️ Cache MISS"]
A_ORIGIN -->|"Serve image"| A_POP
A_POP -->|"Store in memory\n(will be evicted again soon)"| A_C["In-Memory Cache\n(short-lived)"]
end

subgraph WithCR["With Cache Reserve"]
B_USER["User requests\nrare product image"] --> B_POP["Edge PoP"]
B_POP -->|"Not in memory"| B_CR["Cache Reserve\n(R2 — persistent ✅)"]
B_CR -->|"Found in R2\n(no origin call)"| B_POP
B_POP -->|"Serve image"| B_USER
end

style A_ORIGIN fill:#dc2626,color:#fff,stroke:#b91c1c
style B_CR fill:#16a34a,color:#fff,stroke:#15803d

What Is Cache Reserve?

Cache Reserve is a persistent cache layer backed by Cloudflare R2 object storage. When Cache Reserve is enabled, Cloudflare writes cacheable responses to R2. On future cache misses, the edge PoP checks R2 before going to your origin.

Think of it as the difference between RAM and a hard drive:

An in-memory CDN cache is like RAM — blazing fast, but limited and volatile. Cache Reserve is like an SSD connected to every PoP simultaneously — slightly slower than RAM, but persistent, vast, and never evicts content arbitrarily.

Cache LayerBacked BySpeedEvictionSize
Edge in-memoryRAM (per PoP)FastestYes — LRU evictionLimited per PoP
Tiered Cache hubRAM (hub PoP)FastYes — LRU evictionLarger, shared
Cache ReserveR2 object storageFast (no origin RTT)NeverEffectively unlimited
OriginYour serversSlowestN/AYour responsibility

The Full Three-Layer Hierarchy

When both Tiered Cache and Cache Reserve are enabled, Cloudflare's lookup chain becomes:

flowchart LR
USER["User Request"] --> EDGE["Edge PoP\n(Layer 1: In-Memory)"]
EDGE -->|"In-memory HIT"| USER
EDGE -->|"In-memory MISS"| HUB["Tiered Cache Hub\n(Layer 2: In-Memory Hub)"]
HUB -->|"Hub HIT"| EDGE
HUB -->|"Hub MISS"| CR["Cache Reserve\n(Layer 3: R2 Persistent)"]
CR -->|"Reserve HIT (REVALIDATED)"| HUB
CR -->|"Reserve MISS"| ORIGIN["Your Origin Server"]
ORIGIN -->|"Fresh response\n→ stored in R2 + edge"| CR

style EDGE fill:#f6821f,color:#fff,stroke:#e5711e
style HUB fill:#f59e0b,color:#fff,stroke:#d97706
style CR fill:#16a34a,color:#fff,stroke:#15803d
style ORIGIN fill:#6b7280,color:#fff,stroke:#4b5563

Lookup order:

  1. Edge PoP in-memory — instant HIT (fastest)
  2. Tiered Cache hub in-memory — fast HIT from nearby hub (if Tiered Cache enabled)
  3. Cache Reserve (R2) — persistent HIT, no origin call
  4. Origin — only reached when none of the above layers have the content

The result: your origin only receives a request for a given object once per Cache Reserve TTL — regardless of how rarely the object is requested.

How Cache Reserve Stores Content

Cache Reserve stores content in R2 using the same cache key that Cloudflare's edge cache uses. You do not need to manage the R2 bucket — Cloudflare does this automatically using a dedicated, internally managed bucket.

What Gets Stored

Cache Reserve stores responses that are:

  • Eligible for cache (either by default static extension, or via a Cache Rule with "Eligible for cache")
  • Successful responses (HTTP 2xx status codes)
  • Within size limits (up to 512MB per object)

What Does NOT Get Stored

ContentWhy Excluded
Cache-Control: private responsesMust not be shared between users
Cache-Control: no-store responsesExplicitly opted out of all caching
Bypass Cache rule matchesExplicitly bypassed
Non-2xx responsesErrors and redirects are not persisted
Responses with Set-Cookie (usually)May contain user-specific state

Cache Reserve TTL and Revalidation

Cache Reserve uses its own internal TTL separate from the Edge TTL defined in your Cache Rules:

TTL TypeWhat It ControlsDefault
Edge TTL (Cache Rule)How long the in-memory PoP/hub holds contentVaries by plan
Cache Reserve TTLHow long R2 holds the object before revalidating with origin30 days (default)

When the Cache Reserve TTL expires for an object, Cloudflare revalidates with your origin (using conditional requests like If-None-Match / If-Modified-Since). If the origin confirms the content is unchanged (304 Not Modified), the TTL is renewed in R2 without downloading the full object again. Your origin only serves the full body if the content actually changed.

sequenceDiagram
participant PoP as Edge PoP
participant CR as Cache Reserve (R2)
participant ORG as Origin

Note over CR: Cache Reserve TTL expires for /product/image.jpg

PoP->>CR: Fetch /product/image.jpg
CR->>ORG: GET /product/image.jpg\nIf-None-Match: "abc123"
ORG-->>CR: 304 Not Modified (content unchanged)
CR-->>PoP: Serve cached content (TTL renewed in R2)

Note over ORG: ✅ No full file transfer — just a 304 header

Pricing Model

Cache Reserve is billed via R2 pricing on the underlying object storage operations:

MetricCost
Storage~$0.015 per GB per month
Class A Operations (Write to R2 on first cache MISS)$4.50 per million operations
Class B Operations (Read from R2 on Cache Reserve HIT)$0.36 per million operations
Egress from R2 to edgeFree (R2 → Cloudflare network is always free)

The critical insight: reads from Cache Reserve are dramatically cheaper than origin egress. If your origin serves responses via a cloud provider (AWS, GCP, Azure), you pay egress fees for every byte sent. Cache Reserve reads from R2 at $0.36/M operations with zero egress cost — often 10× cheaper than origin bandwidth.

Cost Example

Scenario: E-commerce site, 500,000 product images, 2 million monthly views of long-tail products (those not popular enough to stay in edge memory):

Without Cache ReserveWith Cache Reserve
2M origin requests/month~1,000–5,000 origin requests/month (first-time MISS only)
~4TB origin egress/month~0 origin egress (reads from R2)
$360 AWS egress cost/month~$0.72 R2 Class B reads + ~$0.015/GB storage
~$360+/month~$10–15/month

Enabling Cache Reserve

Prerequisites

  • A paid Cloudflare plan (Pro, Business, or Enterprise)
  • Tiered Cache should be enabled first — Cache Reserve works best positioned after Tiered Cache in the lookup chain (both features are designed to be used together)

Steps

  1. Go to Cloudflare Dashboard → your domain → Caching → Cache Reserve
  2. Toggle "Enable Cache Reserve"
  3. Click Save

That's all — Cloudflare automatically begins storing cacheable responses in the managed R2 bucket.

Verify with Headers

Responses served from Cache Reserve include a specific cf-cache-status value:

cf-cache-statusMeaning
HITServed from edge in-memory cache
MISSNot in any cache; fetched from origin
REVALIDATEDContent found in Cache Reserve (R2), origin confirmed unchanged (304)
UPDATINGStale content served while origin is being contacted for a fresh copy
Check if Cache Reserve is serving a resource
curl -sI https://example.com/product/rare-item.jpg | grep cf-cache-status
# cf-cache-status: REVALIDATED ← served from Cache Reserve ✅

When Cache Reserve Is Worth Enabling

Cache Reserve has a real cost (R2 storage + operations). Evaluate whether it makes sense for your use case:

ScenarioCache Reserve Useful?Reasoning
Large product catalogue (50k+ SKUs) with uneven trafficYesLong-tail product images evicted from in-memory cache → R2 fills the gap
News / media site with large archive of articlesYesOld articles rarely accessed but valid → Cache Reserve prevents origin calls
SaaS dashboard (all dynamic, personalised content)NoContent must be bypassed / not cacheable anyway
Small blog (100 posts, all popular)Not neededContent stays in in-memory cache — eviction unlikely
Video streaming platformYesLarge video files serve from R2 with no egress costs
API with responses tailored per userNoShould not be cached at all

Cache Reserve vs Tiered Cache — Full Comparison

AspectTiered CacheCache Reserve
Problem solvedMultiple PoPs calling origin independently for the same popular contentLong-tail content being evicted from memory between requests
Storage mediumIn-memory (volatile, finite)R2 object storage (persistent, vast)
EvictionYes — LRU❌ None — R2 is persistent storage
SpeedFast (memory)Slightly slower than memory, vastly faster than origin
Free?✅ Generic topology is free❌ Paid (R2 storage costs)
Best forHigh-traffic popular contentLow-traffic, long-tail content with a large asset library
Used together?✅ Yes — complementary✅ Yes — both should be enabled together

Common Misconceptions

"Cache Reserve is just a bigger edge cache"

Reality: Cache Reserve is backed by R2 object storage — fundamentally different from in-memory edge caching. It provides persistence (no eviction) rather than speed. While it is faster than your origin, it is slower than in-memory edge cache for content that fits there.

"Cache Reserve makes Tiered Cache unnecessary"

Reality: They solve different problems. Tiered Cache reduces origin calls for popular content by preventing multiple PoPs from independently calling origin. Cache Reserve prevents origin calls for infrequent content that gets evicted from memory. You want both for maximum origin shielding.

"Enabling Cache Reserve will cache my private user data"

Reality: Cache Reserve never stores responses with Cache-Control: private, no-store, active session cookies, or Bypass Cache rules. Responses that should not be cached are excluded automatically. The same safety rules that protect in-memory edge caching protect Cache Reserve.

"Cache Reserve's TTL is the same as my Edge TTL"

Reality: Cache Reserve has its own 30-day default TTL, independent of the Edge TTL set in your Cache Rules. A resource with a 1-hour Edge TTL may still be in Cache Reserve for 30 days — serving subsequent edge misses without ever asking your origin.

Anti-Patterns to Avoid

Don't Do ThisDo This Instead
Enable Cache Reserve without first enabling Tiered CacheEnable Tiered Cache first — Cache Reserve sits behind it in the lookup chain
Enable Cache Reserve just to cache a small site's 20 imagesOnly enable if you have a large or long-tail asset library where eviction is measurable
Assume Cache Reserve handles purging differentlyPurges from the dashboard or API clear Cache Reserve automatically — no extra steps
Enable Cache Reserve without setting Edge TTL via Cache RulesSet appropriate Cache Rules first so content is actually eligible for caching
Ignore the REVALIDATED cf-cache-statusTrack this header in analytics — it is proof Cache Reserve is working and saving origin calls

Key Takeaways

  • Cache Reserve solves the cache eviction problem — content evicted from in-memory edge cache is still served from persistent R2 storage instead of your origin.
  • It introduces a third cache layer: Edge memory → Tiered Cache hub → Cache Reserve (R2) → Origin.
  • Cache Reserve never evicts content arbitrarily — objects stay in R2 until the TTL expires or you purge them.
  • Default Cache Reserve TTL is 30 days — revalidation sends a conditional request (304) rather than downloading the full content again.
  • Enable Tiered Cache first — they are designed to work together as complementary layers.
  • Best suited for: large product catalogues, media archives, video platforms, and any site with long-tail assets that don't stay in memory.
  • Billed via R2 pricing — typically 10× cheaper than origin egress for sites on cloud infrastructure.
  • Purges automatically propagate through Cache Reserve — no extra steps needed.

What's Next

  • Continue to the next module: DDoS Protection to learn how Cloudflare protects your origin from volumetric attacks.