CDN Architecture: Serving Content at the Edge
Design CDN strategies that reduce latency, offload origin servers, and improve reliability. Covers cache hierarchies, cache invalidation, multi-CDN failover, edge computing, and the configuration patterns that prevent your CDN from serving stale content or bypassing your security controls.
A CDN places copies of your content on servers distributed around the world. When a user in Tokyo requests your website, the response comes from a server in Tokyo — not from your origin server in Virginia. The result is lower latency, reduced origin load, and improved availability.
But a CDN is not a caching proxy you point at your origin and forget. Misconfigured CDNs serve stale content, bypass authentication, cache sensitive data, and create debugging nightmares that are invisible until a customer reports them.
How CDNs Work
Request Flow
1. User requests https://example.com/image.jpg
2. DNS resolves to nearest CDN edge (anycast or GeoDNS)
3. Edge checks local cache
HIT: Return cached response (< 10ms)
MISS: Forward to origin, cache response, return (200ms+)
4. Subsequent requests from same region → cache hit
Cache Hierarchy
Modern CDNs use multiple cache tiers:
Edge PoP (200+ locations worldwide)
↓ miss
Regional Cache (10-20 locations)
↓ miss
Origin Shield (1-3 locations)
↓ miss
Your Origin Server
The origin shield collapses multiple edge misses into a single origin request. Without it, a cache miss at 50 edge locations generates 50 simultaneous origin requests for the same resource.
Cache Control Headers
Your origin server controls CDN caching behavior through HTTP headers:
Cache-Control
# Cache publicly for 1 year (static assets with hash in filename)
Cache-Control: public, max-age=31536000, immutable
# Cache for 1 hour, revalidate when stale
Cache-Control: public, max-age=3600, must-revalidate
# Cache for 5 minutes at CDN, 0 at browser
Cache-Control: public, s-maxage=300, max-age=0
# Never cache (dynamic/authenticated content)
Cache-Control: private, no-store
Key Headers
| Header | Purpose |
|---|---|
Cache-Control | Primary caching directive |
ETag | Content hash for revalidation |
Last-Modified | Timestamp for revalidation |
Vary | Cache separate versions by header (Accept-Encoding, Cookie) |
CDN-Cache-Control | CDN-specific override (Cloudflare, Fastly) |
Common Mistake: Vary: Cookie
Vary: Cookie
This tells the CDN to cache a separate version for every unique cookie value. If your site sets analytics cookies, every user gets a unique cache entry — effectively disabling caching. Strip unnecessary cookies at the edge or use CDN-Cache-Control to override.
Cache Invalidation Strategies
Time-Based (TTL)
Set appropriate TTLs for different content types:
Static assets (hashed): 1 year (immutable)
Marketing pages: 1 hour
API responses: 1-5 minutes
User-specific content: 0 (no cache)
Content Hashing
Include a hash in the filename so every content change creates a “new” URL:
/assets/main.a1b2c3d4.css → cached forever
/assets/main.e5f6g7h8.css → new content, new URL, no invalidation needed
This is the most reliable cache invalidation strategy because it sidesteps invalidation entirely.
Purge API
When you need immediate invalidation:
# Cloudflare
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone}/purge_cache" \
-H "Authorization: Bearer {token}" \
-d '{"files": ["https://example.com/page.html"]}'
# Fastly
curl -X PURGE "https://example.com/page.html" \
-H "Fastly-Key: {key}"
Surrogate Keys (Tag-Based Purge)
Tag cached objects with logical identifiers and purge by tag:
# Response header from origin
Surrogate-Key: product-123 category-electronics homepage
# Purge everything related to product 123
curl -X POST "https://api.fastly.com/service/{id}/purge/product-123"
This purges every page that displays product 123 — product detail, category listing, homepage featured section — in one API call.
Security Considerations
Origin Protection
Your origin should only accept requests from the CDN:
# Origin server: Allow only CDN IPs
allow 103.21.244.0/22; # Cloudflare
allow 103.22.200.0/22;
deny all;
Or use origin pull certificates for mutual TLS authentication between CDN and origin.
Caching Sensitive Content
Never cache responses that contain:
- Personal user data (profiles, account pages)
- Authentication tokens (Set-Cookie with session IDs)
- Financial data (billing, payment confirmations)
Ensure these responses include Cache-Control: private, no-store.
Cache Poisoning
If an attacker can manipulate cache keys (via headers, query params, or request paths), they can poison the cache with malicious content for all users. Mitigation:
- Normalize cache keys (strip unnecessary query parameters)
- Validate and sanitize all inputs that affect response content
- Use WAF rules at the edge
Multi-CDN Architecture
For high-availability requirements, route traffic across multiple CDN providers:
DNS (Route53 / Cloudflare DNS)
├── 70% → Primary CDN (Cloudflare)
└── 30% → Secondary CDN (Fastly)
OR
└── Failover → Secondary (if primary health check fails)
Benefits
- No single CDN provider as a point of failure
- Leverage each CDN’s geographic strengths
- Negotiating power on pricing
Challenges
- Cache invalidation must be executed on all CDNs
- Configuration drift between providers
- Different feature sets and edge APIs
Anti-Patterns
| Anti-Pattern | Consequence | Fix |
|---|---|---|
| No cache versioning | Users see stale CSS/JS after deploy | Hash filenames or use purge API |
| Caching authenticated pages | User A sees User B’s data | Cache-Control: private, no-store |
| Origin not protected | Attackers bypass CDN, hit origin directly | IP allowlist or origin certificates |
| Vary: Cookie | Every user gets unique cache entry | Strip unnecessary cookies at edge |
| No origin shield | Cache miss storm at 200 edges | Enable origin shield to collapse requests |
A CDN is one of the highest-ROI infrastructure investments you can make — milliseconds of improvement in latency translate directly to engagement and conversion metrics. But the investment is in configuration, not just activation.