CDN Deep Dive 2026 — Edge Architecture, Cache Invalidation and Cloudflare vs CloudFront vs Azure Front Door
Posted on: 4/21/2026 5:13:36 PM
Table of contents
- 1. Modern CDN Architecture — From Reverse Proxy to Edge Platform
- 2. Cache-Control — The Language Between Origin and CDN
- 3. Cache Invalidation — The Hardest CDN Problem
- 4. Cloudflare CDN — Zero Bandwidth Cost, Full-Stack Edge
- 5. AWS CloudFront — Power of the AWS Ecosystem
- 6. Azure Front Door — CDN with Integrated Load Balancing
- 7. Comprehensive Comparison — Cloudflare vs CloudFront vs Azure Front Door
- 8. Designing a CDN Layer for Production
- 9. Real-World Costs — Can CDN Be Free?
- 10. Conclusion
When a website serves users from Hanoi to São Paulo, Tokyo to Berlin, the physical distance between the origin server and browser becomes the biggest bottleneck. Content Delivery Networks (CDNs) solve this by placing content replicas at hundreds of Points of Presence (PoPs) worldwide. In 2026, CDNs are no longer just static file caches — they've evolved into edge computing platforms capable of running code, processing images, blocking DDoS attacks, and optimizing routing in real time. This article analyzes modern CDN architecture, compares the three largest platforms (Cloudflare, AWS CloudFront, Azure Front Door), and dives deep into cache invalidation strategies for production systems.
1. Modern CDN Architecture — From Reverse Proxy to Edge Platform
CDNs work on a simple principle: bring content as close to the user as possible. But the implementation of this principle has changed dramatically over the past five years.
1.1. Two-Tier vs Single-Tier Architecture
There are two main CDN architecture philosophies in 2026, each with fundamentally different design approaches:
graph TB
subgraph "Two-Tier (CloudFront)"
U1["User"] --> E1["Edge PoP
(600+ locations)"]
E1 -->|"Cache Miss"| R1["Regional Edge Cache
(13 regions)"]
R1 -->|"Cache Miss"| OS1["Origin Shield
(1 region)"]
OS1 -->|"Cache Miss"| O1["Origin Server"]
end
subgraph "Single-Tier (Cloudflare)"
U2["User"] --> E2["Edge PoP
(310+ cities)"]
E2 -->|"Cache Miss"| TC["Upper-Tier PoP
(Tiered Cache)"]
TC -->|"Cache Miss"| O2["Origin Server"]
end
style E1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style R1 fill:#e94560,stroke:#fff,color:#fff
style OS1 fill:#2c3e50,stroke:#e94560,color:#fff
style O1 fill:#16213e,stroke:#e94560,color:#fff
style E2 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style TC fill:#e94560,stroke:#fff,color:#fff
style O2 fill:#16213e,stroke:#e94560,color:#fff
Figure 1: Two-Tier (CloudFront) vs Single-Tier (Cloudflare) architecture comparison
CloudFront uses a three-layer architecture: Edge Location → Regional Edge Cache → Origin Shield → Origin. Each layer serves a specific function, creating multiple cache hit opportunities but also increasing latency on misses.
Cloudflare employs a simpler anycast model: every server at every PoP runs the entire software stack — caching, WAF, DDoS mitigation, SSL termination, Workers compute — in a single processing pass. With Tiered Cache, Cloudflare adds an upper-tier PoP layer to reduce origin requests.
1.2. Request Lifecycle Through a CDN
sequenceDiagram
participant B as Browser
participant DNS as DNS Resolver
participant E as Edge PoP
participant O as Origin Server
B->>DNS: Resolve cdn.example.com
DNS-->>B: Anycast IP (nearest PoP)
B->>E: GET /api/products (TLS 1.3)
Note over E: Check Cache Key
(URL + headers + query)
alt Cache HIT
E-->>B: 200 OK (X-Cache: HIT, ~28ms)
else Cache MISS
E->>O: Forward request
O-->>E: 200 OK + Cache-Control headers
Note over E: Store in cache
Apply TTL + tags
E-->>B: 200 OK (X-Cache: MISS, ~120ms)
end
Figure 2: Request lifecycle through CDN — from DNS resolution to cache response
2. Cache-Control — The Language Between Origin and CDN
The Cache-Control header is the primary mechanism for origin servers to instruct CDNs on caching behavior. Misunderstanding this header is the most common cause of caching issues in production.
2.1. Key Directives
| Directive | Meaning | Usage Example |
|---|---|---|
max-age=N | Cache for N seconds from response time | Static assets: max-age=31536000 (1 year) |
s-maxage=N | TTL specifically for shared caches (CDN), overrides max-age | API response: s-maxage=60, max-age=0 |
stale-while-revalidate=N | Serve stale content for N seconds while revalidating | s-maxage=300, stale-while-revalidate=60 |
stale-if-error=N | Serve stale if origin returns error within N seconds | Fallback when origin is down |
no-store | Do not cache anywhere | Responses containing sensitive data |
no-cache | Cache but revalidate before every use | Content that must always be fresh |
private | Browser cache only, CDN must not cache | User-specific response data |
# Nginx — Cache-Control configuration for different content types
# Static assets (CSS, JS, images) — cache 1 year, immutable
location ~* \.(css|js|woff2|webp|avif|svg)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
# HTML pages — CDN cache 5 min, browser no cache
location ~* \.html$ {
add_header Cache-Control "public, s-maxage=300, max-age=0, must-revalidate";
}
# API responses — CDN cache 1 min, serve stale 30s during revalidation
location /api/ {
add_header Cache-Control "public, s-maxage=60, stale-while-revalidate=30, stale-if-error=300";
}
# User-specific data — no CDN caching
location /api/me/ {
add_header Cache-Control "private, no-cache";
}
2.2. CDN-Cache-Control — CDN-Specific Header
Cloudflare supports the CDN-Cache-Control header (per RFC 9213), allowing origins to set CDN-specific caching directives without affecting browser cache behavior. This is the solution when you want CDN to cache longer than the browser:
// ASP.NET Core — set separate CDN-Cache-Control and browser Cache-Control
app.Use(async (context, next) =>
{
await next();
if (context.Request.Path.StartsWithSegments("/api/products"))
{
// CDN: cache 5 minutes, stale-while-revalidate 30s
context.Response.Headers["CDN-Cache-Control"] = "max-age=300, stale-while-revalidate=30";
// Browser: always revalidate
context.Response.Headers["Cache-Control"] = "no-cache";
}
});
3. Cache Invalidation — The Hardest CDN Problem
Phil Karlton once said: "There are only two hard things in Computer Science: cache invalidation and naming things." With CDNs distributed across hundreds of PoPs, invalidation becomes a real production challenge.
3.1. Four Invalidation Strategies
graph LR
subgraph "TTL-Based"
A1["Set TTL
max-age=300"] --> A2["Auto expire
after 5 min"]
end
subgraph "Purge by URL"
B1["Content changed"] --> B2["API: purge
/path/to/page"]
end
subgraph "Tag-Based Purge"
C1["Tag responses
Cache-Tag: product-123"] --> C2["Purge tag
→ invalidate all"]
end
subgraph "Versioned URLs"
D1["style.v3.css"] --> D2["New deploy:
style.v4.css"]
end
style A1 fill:#f8f9fa,stroke:#4CAF50,color:#2c3e50
style A2 fill:#f8f9fa,stroke:#4CAF50,color:#2c3e50
style B1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style B2 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style C1 fill:#f8f9fa,stroke:#2196F3,color:#2c3e50
style C2 fill:#f8f9fa,stroke:#2196F3,color:#2c3e50
style D1 fill:#f8f9fa,stroke:#ff9800,color:#2c3e50
style D2 fill:#f8f9fa,stroke:#ff9800,color:#2c3e50
Figure 3: Four common Cache Invalidation strategies
| Strategy | Speed | Precision | Best For |
|---|---|---|---|
| TTL-Based | Automatic, no action needed | Low — stale within TTL window | Infrequently changing content, eventual consistency OK |
| Purge by URL | Fast (< 1s on Cloudflare) | High — precise per URL | Known URLs needing invalidation |
| Tag-Based Purge | Fast — 1 command purges many URLs | Very high — grouped by logic | Cannot enumerate all affected URLs |
| Versioned URLs | Instant — new URL = cache miss | Absolute — never stale | Static assets (CSS, JS, images) |
3.2. Tag-Based Purge — The Production Strategy
Tag-based purge (or Surrogate Keys) is the most powerful method for complex systems. The idea: each response is tagged with one or more cache tags, and when data changes, you purge by tag instead of listing individual URLs.
// ASP.NET Core — Attach Cache-Tags to responses
app.MapGet("/api/products/{id}", async (int id, ProductService service) =>
{
var product = await service.GetByIdAsync(id);
return Results.Ok(product);
})
.AddEndpointFilter(async (context, next) =>
{
var result = await next(context);
var id = context.GetArgument<int>(0);
var httpContext = context.HttpContext;
// Attach multiple tags to a single response
httpContext.Response.Headers["Cache-Tag"] =
$"product-{id},category-{product.CategoryId},all-products";
httpContext.Response.Headers["Cache-Control"] =
"public, s-maxage=3600, stale-while-revalidate=60";
return result;
});
// When product changes → purge tags
app.MapPut("/api/products/{id}", async (int id, Product updated,
ProductService service, ICdnPurgeService cdn) =>
{
await service.UpdateAsync(id, updated);
await cdn.PurgeTagsAsync($"product-{id}", "all-products");
return Results.Ok(updated);
});
3.3. Stale-While-Revalidate — Never Wait for Origin
The stale-while-revalidate directive is the secret weapon for eliminating latency spikes when cache expires. After TTL expiration, the CDN still returns the old (stale) response immediately while fetching a fresh version from origin in the background.
sequenceDiagram
participant U as User
participant CDN as CDN Edge
participant O as Origin
Note over CDN: Cache TTL expired
stale-while-revalidate=60
U->>CDN: GET /api/data
CDN-->>U: 200 OK (stale data, ~30ms)
CDN->>O: Background revalidate
O-->>CDN: 200 OK (fresh data)
Note over CDN: Cache updated
New TTL starts
U->>CDN: GET /api/data (next request)
CDN-->>U: 200 OK (fresh data, ~30ms)
Figure 4: Stale-While-Revalidate — users always get fast responses, revalidation runs in background
When to use stale-while-revalidate?
This pattern is ideal for content that tolerates staleness for a few seconds: product listings, blog posts, config data, dashboard metrics. Not suitable for financial data, inventory counts, or anything requiring strong consistency.
4. Cloudflare CDN — Zero Bandwidth Cost, Full-Stack Edge
Cloudflare is the default choice for 80% of websites in 2026, thanks to its market-breaking pricing model: $0 bandwidth cost across all plans, including Free.
4.1. Cache Rules 2026 — New Features
In March 2026, Cloudflare introduced Cache Response Rules with three new capabilities:
| Feature | Description | Use Case |
|---|---|---|
| Independent Browser TTL | Set browser Cache-Control different from edge cache TTL | Edge cache 1 hour, browser cache 5 minutes |
| Cache Tag Management | Add/modify/remove cache tags on responses | Convert tag formats when migrating from another CDN |
| Strip Caching Blockers | Remove Set-Cookie, ETag from origin responses before caching | Cache responses where origin sets unnecessary cookies |
4.2. Tiered Cache — Reducing Origin Load
Cloudflare Tiered Cache (free from the Free plan) adds a cache layer between edge PoPs and origin. Instead of 310+ PoPs all fetching origin on miss, only selected upper-tier PoPs contact origin. Result: 60-90% reduction in origin requests.
graph TB
U["Users worldwide"] --> E1["Edge PoP
Hanoi"]
U --> E2["Edge PoP
HCM"]
U --> E3["Edge PoP
Bangkok"]
U --> E4["Edge PoP
Tokyo"]
E1 -->|"Miss"| T1["Upper-Tier
Singapore"]
E2 -->|"Miss"| T1
E3 -->|"Miss"| T1
E4 -->|"Miss"| T2["Upper-Tier
Tokyo"]
T1 -->|"Miss"| O["Origin Server
US-East"]
T2 -->|"Miss"| O
style E1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style E2 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style E3 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style E4 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style T1 fill:#e94560,stroke:#fff,color:#fff
style T2 fill:#e94560,stroke:#fff,color:#fff
style O fill:#2c3e50,stroke:#e94560,color:#fff
Figure 5: Cloudflare Tiered Cache — only upper-tier PoPs contact origin
5. AWS CloudFront — Power of the AWS Ecosystem
5.1. Origin Shield — The Third Cache Layer
CloudFront Origin Shield is a paid feature (~$0.0035/10K requests) that creates an additional centralized cache layer. All miss requests from Regional Edge Caches pass through Origin Shield before reaching origin, enabling:
- Higher cache hit ratio: multiple Regional Edge Caches share one Origin Shield
- Request coalescing: multiple requests for the same object are merged into 1 origin request
- Reduced origin costs: especially useful when origin performs heavy processing (image transformation, video transcoding)
5.2. Lambda@Edge vs CloudFront Functions
| Criteria | CloudFront Functions | Lambda@Edge |
|---|---|---|
| Runtime | JavaScript (ECMAScript 5.1) | Node.js, Python |
| Execution time | < 1ms | Up to 30s (origin events) |
| Memory | 2 MB | Up to 10 GB |
| Network access | No | Yes |
| Pricing | $0.10/million invocations | $0.60/million + duration |
| Use case | URL rewrite, header manipulation, cache key normalization | A/B testing, auth check, image optimization, SSR |
6. Azure Front Door — CDN with Integrated Load Balancing
Azure Front Door combines CDN, global load balancing, WAF, and SSL offloading in a single service. Its greatest strength: deep integration with the Azure ecosystem (App Service, Container Apps, Static Web Apps).
Azure Front Door Cache Purge Latency
As of April 2026, Azure Front Door cache purge can take up to 20 minutes to propagate globally. Microsoft has not committed to a purge latency SLA. If you need instant invalidation, combine with versioned URLs for static assets or consider Cloudflare (purge < 1 second).
7. Comprehensive Comparison — Cloudflare vs CloudFront vs Azure Front Door
| Criteria | Cloudflare | AWS CloudFront | Azure Front Door |
|---|---|---|---|
| PoPs | 310+ cities, 120+ countries | 600+ edge, 13 regional | 192+ PoPs |
| Median TTFB (cached) | 28ms | 35ms | ~40ms |
| Bandwidth cost | $0 (all plans) | $0.085/GB (US), volume discounts | ~$0.08/GB (varies) |
| Free tier | Unlimited bandwidth, 100K Workers/day | 1TB/month (first 12 months) | No free CDN tier |
| Edge compute | Workers (V8 isolates, 0ms cold start) | Lambda@Edge + CF Functions | Rules Engine (limited logic) |
| DDoS protection | Unlimited, free on all plans | Shield Standard free, Advanced $3K/mo | Standard free, Premium paid |
| WAF | Included from Free plan (managed rules) | WAF v2 separate (~$5/rule) | Integrated (Standard/Premium) |
| Cache purge speed | < 1 second globally | < 60 seconds | Up to 20 minutes |
| Tag-based purge | Enterprise plan | Not natively supported | Not supported |
| Best for | Most websites, cost-sensitive, edge-first | AWS-native workloads, S3 origins | Azure-native, multi-region apps |
8. Designing a CDN Layer for Production
graph TB
U["Users"] --> CDN["CDN Edge
(Cloudflare/CloudFront)"]
CDN -->|"Static assets
Cache 1 year"| S3["Object Storage
(S3/R2)"]
CDN -->|"API responses
Cache 5 min"| API["API Server
(.NET / Node.js)"]
CDN -->|"HTML pages
SWR 60s"| SSR["SSR Server
(Nuxt/Next)"]
API --> DB["Database"]
DB -->|"Change Event"| WH["Webhook Handler"]
WH -->|"Purge tags"| CDN
CI["CI/CD Pipeline"] -->|"Purge on deploy"| CDN
CMS["CMS / Admin"] -->|"Purge on publish"| CDN
style CDN fill:#e94560,stroke:#fff,color:#fff
style S3 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style API fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style SSR fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style WH fill:#2c3e50,stroke:#e94560,color:#fff
style DB fill:#16213e,stroke:#e94560,color:#fff
Figure 6: Production CDN architecture with multiple invalidation triggers
Golden Rule
TTL for day-to-day, purge for emergencies. Set reasonable TTLs (5-60 minutes for APIs, 1 year for static assets with versioned URLs) as the primary strategy. Only use purge when instant invalidation is needed — purging on every request is an anti-pattern that defeats the purpose of a CDN.
9. Real-World Costs — Can CDN Be Free?
With Cloudflare's Free plan, the answer is yes for most websites:
When is CloudFront/Azure Front Door still the right choice?
When your system already lives entirely within AWS or Azure. Data transfer between CloudFront and S3/ALB/API Gateway in the same region is discounted or free. The CDN bandwidth cost is offset by reduced egress from origin. Similarly, Azure Front Door combined with Azure Static Web Apps (free tier) creates a very cost-effective stack.
10. Conclusion
CDN in 2026 is no longer "nice to have" — it's a mandatory component of every production web architecture. With Cloudflare offering CDN + WAF + DDoS protection for free, there's no reason for any website to operate without a CDN.
For caching strategy: versioned URLs for static assets (cache forever, never stale), s-maxage + stale-while-revalidate for API responses (fast, eventually consistent), and tag-based purge for content requiring precise invalidation. This is a proven formula at production scale.
Finally, choosing a CDN provider depends on your existing ecosystem. Starting fresh or cost-sensitive? Cloudflare is the default. Deep into AWS? CloudFront + Origin Shield provides the best integration. Azure Front Door fits when you need CDN + global load balancer + WAF in a single Azure-native service.
References
- Cloudflare vs CloudFront 2026: 20% TTFB Gap and $3,900 Cost Divide — Tech Insider
- Cache Rules — Cloudflare Docs
- CDN-Cache-Control — Cloudflare Docs
- Cache Response Rules (March 2026) — Cloudflare Changelog
- CloudFront Origin Shield — AWS Documentation
- Azure Front Door Caching — Microsoft Learn
- CDN Showdown: Cloudflare vs CloudFront vs Azure CDN vs Google Cloud CDN — InventiveHQ
- Designing CDN Caching: Cache-Control, Surrogate Keys, Tag-based Purging — DEV Community
Webhook Design Patterns — Building Reliable Event Notification Systems
Server-Sent Events — Building a Real-time Dashboard with .NET 10, Vue 3 & Redis
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.