Single-tier edge caching no longer holds up under modern traffic patterns. With cache key explosion from personalization, short TTLs for real-time content, and thundering herds after a purge, a single layer of edge PoPs will push 10-15% of requests back to origin. Multi-tier caching solves this by creating a hierarchy of caches between user and origin, lifting global hit ratios from ~88% to 96-98% while cutting origin egress by 70-90%.
This architecture is now standard at Cloudflare, Fastly, Akamai, and AWS CloudFront. Understanding how L1, L2, and Shield interact is essential for tuning caching strategies, sizing origin, and controlling cost.
Why a Single Tier Fails at Scale
A flat CDN with 300+ edge PoPs means each PoP holds a small, fragmented slice of your working set. A URL requested 1,000 times per minute globally might be requested only 3 times per minute per PoP — not enough to stay hot in RAM. Result: frequent evictions, low byte-hit ratio, and synchronized misses that hit origin simultaneously.
Multi-tiering introduces aggregation. Instead of 300 independent caches, you funnel misses into fewer, larger caches. Each upstream tier sees 10-30x more requests for the same object, so it stays warm. It also enables collapsed forwarding and stale-while-revalidate at the shield, which are impossible to coordinate across isolated edges.
Tier 1: Edge Cache (L1)
L1 is the outermost layer — 150 to 400+ Points of Presence deployed as close to users as possible, often inside ISPs and IXPs. Its job is latency, not capacity.
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
- Storage: Primarily RAM (128-512 GB per server) + small NVMe for hot objects. Working set per PoP is typically 10-100 GB.
- Latency: 5-25 ms HIT, 40-80 ms MISS to L2.
- Eviction: Aggressive LRU/LFU with TTLs honored strictly. Objects with TTL < 60s may not be cached at L1 at all.
- Features: TLS termination, HTTP/2 & HTTP/3, request collapsing, tiered cache-key normalization.
L1 handles the majority of traffic volume. A well-tuned L1 hit ratio of 75-85% is good, but insufficient alone. The remaining 15-25% is where L2 proves its value. For performance context, see how edge hits affect CDN performance and security.
L1 Optimization Tips
Keep cache keys lean. Normalize query strings, strip marketing params (utm_*, fbclid), and sort remaining params. Use Vary sparingly — each variant multiplies cache keys. Enable collapsed forwarding (request coalescing) so 50 simultaneous misses for the same object result in one upstream fetch.
Tier 2: Regional Edge Cache (L2)
L2 is the mid-tier — 10 to 30 regional hubs that aggregate multiple L1 PoPs. In AWS CloudFront these are Regional Edge Caches; in Akamai they are parent clusters; in Fastly they are shield PoPs used as L2.
- Storage: Large NVMe/SSD pools, 5-50 TB per cluster, optimized for byte-hit ratio over latency.
- Latency: 15-45 ms from L1, still far faster than origin (80-250 ms).
- Hit Ratio: L2 adds 8-12% absolute hit ratio on top of L1.
- Role: Absorbs long-tail content, large objects, and cache fragmentation.
Example: A product image requested in Dallas, Houston, and Miami L1s would miss at each L1 on first fetch. With L2, only the first L1 misses to L2, the next two hit L2 in the US-Central region. Origin sees one request instead of three.
L2 is also where you run heavier logic: image optimization, edge SSR revalidation, and cache observability sampling, without burdening latency-sensitive L1 workers.
Shield Cache: Origin Shield
Shield (also called Origin Shield) is a single logical tier directly in front of origin — often 1-2 PoPs per origin region, chosen for proximity to origin, not users. All L2 misses converge here.
Unlike L1/L2 which are geographically distributed for latency, shield is centralized for coalescing. Its guarantees:
- Origin protection: Collapses 100+ concurrent misses into 1 origin fetch via request coalescing + locking.
- Stale serving: Serves stale on origin 5xx or timeout (stale-if-error, stale-while-revalidate).
- Write shielding: Buffers purges and revalidations so origin never sees a thundering herd after invalidation.
Without shield, a purge of a popular API endpoint with 20k RPS globally could send 3,000-5,000 RPS to origin in the first second. With shield, origin sees 1 RPS. This is non-negotiable for e-commerce and API workloads. The cost of shield egress is typically 10-20% of direct origin egress, paying for itself immediately.
End-to-End Request Flow
Comparing the Tiers
| Tier | Location & Count | Hit Latency | Capacity & Media | Primary Goal |
|---|---|---|---|---|
| L1 Edge | ISP/IXP, 150–400+ PoPs | 5–25 ms | 128–512 GB RAM, small NVMe | Lowest TTFB, TLS offload |
| L2 Regional | Regional hubs, 10–30 clusters | 15–45 ms | 5–50 TB SSD/NVMe | Aggregation, byte-hit ratio |
| Shield | Near origin, 1–2 PoPs | 40–80 ms | 50–200 TB SSD, large object store | Origin protection, coalescing |
| Origin | Your data center / cloud | 80–300 ms | Unlimited (but expensive) | Source of truth |
Cache Keys, TTLs, and Code
Multi-tier only works if cache keys are consistent across tiers. A key mismatch between L1 and L2 causes a false miss and defeats aggregation.
1. Normalized Cache Key
Include only what changes the response: path, sorted query allowlist, content negotiation headers. Exclude cookies, user-agent, and marketing params at L1.
sub vcl_hash {
hash_data(req.url.path);
if (req.url.qs ~ "lang|cur|ver") {
set req.url.qs = querystring.sort(req.url.qs);
hash_data(req.url.qs);
}
if (req.http.Accept-Language ~ "^en") { hash_data("en"); }
return (lookup);
}
2. Tiered TTLs with Stale Controls
Use longer TTLs upstream. L1 can have 30s TTL while L2/shield hold 300s with stale-while-revalidate. Shield serves stale to L2 while revalidating once to origin.
Cache-Control: public, max-age=30, s-maxage=300
Surrogate-Control: max-age=300, stale-while-revalidate=60, stale-if-error=86400
Surrogate-Key: product/1234 category/shoes
CDN-Cache-Control: max-age=300
This pattern lets L1 stay fresh for users while L2/shield absorb revalidation storms. Pair it with precise cache invalidation via surrogate keys instead of URL purges.
Shield Topologies
Single Global Shield — one shield PoP (e.g., us-east-1) for a single origin. Simplest, best coalescing, but adds 50-100 ms for distant L2 misses. Ideal for single-region origins.
Regional Shield — one shield per origin region (US, EU, APAC) with origin failover. Lower latency, but requires replication or global datastore. Use when origin is multi-region or latency-sensitive.
Hierarchical Shield — L2 → Regional Shield → Global Shield → Origin. Used by Akamai and Cloudflare Enterprise for massive catalogs. Maximizes hit ratio at cost of complexity.
Select based on origin location and traffic distribution. For most teams, start with a single shield closest to origin, then add regional shields when cross-region L2→shield latency exceeds 60 ms p95.
Performance and Cost Impact
Moving from single-tier to three-tier typically yields:
- Cache hit ratio: 86% → 97% (global), byte-hit ratio: 78% → 94%
- Origin RPS: -85% to -95%, egress: -70% to -90%
- p95 TTFB: -15% to -30% for tail content, p99 origin CPU: -60%
The cost math is compelling. Origin egress at $0.08/GB vs. shield egress at $0.02/GB plus cache fill fees means break-even at ~15% hit ratio improvement. Most see 3-6x ROI within one billing cycle, especially for video, images, and API responses.
Pitfalls and Best Practices
1. Avoid Cache Key Fragmentation
Do not forward Cookie or Authorization to cache key by default. Use Vary: Accept-Encoding only. Each additional Vary value halves effective hit ratio.
2. Purge Correctly
Never purge by wildcard at L1. Use surrogate keys and soft purge: mark stale at shield, let L2/L1 revalidate with If-None-Match. This keeps hit ratio high during deployments.
3. Monitor Per-Tier
Track hit ratio, latency, and origin offload per tier separately. A 95% global hit ratio can hide a 60% L1 hit ratio with overloaded L2. Alert on shield miss rate > 2% and L2→shield latency p95 > 50 ms.
4. Size Shield for Writes
Shield needs high write throughput for cache fills. Provision NVMe with high IOPS and enable large object optimization (chunked caching > 10 MB). Without it, large file fills will evict hot small objects.
Multi-tier caching is not optional at scale — it is the difference between an origin that survives a flash sale and one that collapses. Start with L1 + Shield, add L2 when your working set exceeds L1 RAM or your origin sees >5% of global traffic. Measure per-tier hit ratios, normalize keys, and let shield absorb the chaos so origin stays calm. For a full implementation checklist, review our guide to CDN monitoring and observability.
Frequently Asked Questions
What is the difference between L1, L2, and shield cache?
L1 is the edge cache in 150+ PoPs serving users directly with ~10-30ms latency. L2 is a larger regional cache aggregating 10-20 L1 PoPs with higher hit ratio and SSD capacity. Shield is a single global or per-region layer in front of origin that collapses all misses into one origin request, protecting origin from thundering herd.
Does multi-tier caching increase TTFB?
For L1 hits, no. For L1 misses that hit L2, TTFB increases by 15-40ms vs. origin, but is still 3-5x faster than origin fetch. The trade-off is vastly higher overall cache hit ratio (95-98% vs 85-90% with single tier) and lower origin load.
When should you use origin shield?
Always for dynamic or high-cardinality content, e-commerce, and any origin with limited concurrency. Shield is critical when cache TTLs are short (<60s), during cache purges, and for large file delivery where origin egress is expensive.
How do you handle cache invalidation with multiple tiers?
Use surrogate keys and soft purge. Purge propagates top-down: shield → L2 → L1 via broadcast or versioned keys. Soft purge serves stale while revalidating at shield only, preventing stampede. Avoid wildcard purges; use key-based invalidation.