CDN Basics
Understand how Content Delivery Networks bring your content closer to users worldwide. Learn how edge servers, caching, and geographic distribution eliminate latency — and why every production frontend relies on a CDN.
Table of Contents
Overview
A CDN (Content Delivery Network) is a globally distributed network of servers that caches and serves content from locations physically close to users. Instead of every request traveling to your origin server in one region, a CDN serves cached copies from the nearest edge server — cutting latency from 200ms+ to under 20ms.
CDNs are the backbone of modern web performance. Every major website — Google, Netflix, Amazon, Shopify — uses a CDN to deliver static assets (JS, CSS, images, fonts) and increasingly dynamic content too. Without a CDN, users far from your server experience painfully slow load times.
For frontend system design interviews, CDNs come up in almost every architecture discussion. You need to know what they cache, how they interact with HTTP caching headers, and when to use them vs when they don't help.
Why this matters
A CDN can reduce page load times by 50-70% for users far from your origin server. It's often the single biggest performance improvement you can make with the least code change — just point your DNS at a CDN and configure caching headers.
The Problem: Distance & Latency
Data travels through fiber optic cables at roughly two-thirds the speed of light. That sounds fast, but the Earth is big. A round trip from Mumbai to Virginia takes ~200ms just for the signal to travel — before any server processing happens.
Origin server: US-East (Virginia) User in New York → ~ 10ms round trip ✅ Fast User in London → ~ 80ms round trip ⚠️ Noticeable User in Mumbai → ~ 200ms round trip ❌ Slow User in Sydney → ~ 250ms round trip ❌ Very slow User in São Paulo → ~ 150ms round trip ❌ Slow Each HTTP request pays this cost: DNS: 1 round trip → 200ms TCP: 1 round trip → 200ms TLS: 1 round trip → 200ms Request: 1 round trip → 200ms Total for first request from Mumbai: ~800ms And that's BEFORE the server processes anything. A page with 30 resources = 30× this cost (mitigated by HTTP/2 multiplexing, but the base latency remains).
Physics Limit
Light in fiber travels at ~200,000 km/s. New York to Sydney is 16,000 km. The absolute minimum round trip is ~160ms. You can't beat physics — but you can move the server closer.
Compounding Latency
Each resource on a page needs at least 1 round trip. A page with images, CSS, JS, and fonts makes dozens of requests. High base latency multiplies across every resource.
User Experience
Research shows 100ms feels instant, 300ms feels sluggish, and 1000ms+ causes users to lose focus. A 200ms base latency puts you in 'sluggish' territory before any work is done.
The core insight
You can't make light travel faster. But you can move the content closer to the user. That's exactly what a CDN does — it puts copies of your content on servers around the world, so the nearest copy is always close.
What Is a CDN?
A CDN is a network of servers (called edge servers or PoPs — Points of Presence) distributed across dozens or hundreds of locations worldwide. When a user requests a resource, the CDN routes the request to the nearest edge server, which serves a cached copy of the content.
┌─────────────────┐ │ Origin Server │ │ (US-East) │ │ Your app code │ │ Your database │ └────────┬────────┘ │ Fetches from origin on cache miss │ ┌───────────────────┼───────────────────┐ │ │ │ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │ Edge │ │ Edge │ │ Edge │ │ London │ │ Mumbai │ │ Tokyo │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ Serves cached Serves cached Serves cached content to content to content to EU users Asia users APAC users │ │ │ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │ 👤 User │ │ 👤 User │ │ 👤 User │ │ Berlin │ │ Delhi │ │ Osaka │ │ ~15ms │ │ ~10ms │ │ ~8ms │ └─────────┘ └─────────┘ └─────────┘ Without CDN: Delhi user → US-East = ~200ms With CDN: Delhi user → Mumbai edge = ~10ms Improvement: 95% latency reduction
Major CDN Providers
| Provider | Edge Locations | Common Use |
|---|---|---|
| Cloudflare | 300+ cities | Full-stack CDN, DDoS protection, edge compute |
| AWS CloudFront | 450+ PoPs | Integrated with AWS services, S3 origin |
| Vercel Edge Network | Global | Next.js deployments, serverless functions |
| Fastly | 90+ PoPs | Real-time purging, edge compute (Wasm) |
| Akamai | 4,000+ locations | Enterprise, media streaming, security |
CDN vs hosting
A CDN is not a replacement for your server — it's a layer in front of it. Your origin server still handles dynamic logic, database queries, and authentication. The CDN handles the delivery of cacheable content, shielding your origin from most traffic.
How a CDN Works
When you put a CDN in front of your origin server, every request goes through the CDN first. The CDN decides whether to serve from cache or fetch from the origin. Here's the step-by-step flow.
User requests a resource
The user's browser requests https://cdn.example.com/app.js. DNS resolves this to the nearest CDN edge server (based on the user's geographic location via Anycast routing).
Request hits the nearest edge server
The CDN edge server in the user's region receives the request. It checks its local cache: do I have a fresh copy of /app.js?
Cache hit → serve immediately
If the edge has a cached copy that hasn't expired (based on Cache-Control headers), it serves it directly. The origin server is never contacted. Response time: 5-20ms.
Cache miss → fetch from origin
If the edge doesn't have the resource (first request) or the cache has expired, it forwards the request to the origin server, fetches the response, caches it locally, and serves it to the user.
Cache the response for future requests
The edge server stores the response according to the Cache-Control headers. Subsequent requests from any user in that region get the cached copy — no origin contact needed.
── Cache HIT (fast path) ────────────────────────── User (Delhi) → Edge (Mumbai): "GET /app.a1b2c3.js" Edge cache: ✅ Found, still fresh (max-age not expired) Edge → User: 200 OK + cached content Time: ~10ms total Origin server: not contacted ── Cache MISS (slow path, first request) ────────── User (Delhi) → Edge (Mumbai): "GET /app.a1b2c3.js" Edge cache: ❌ Not found Edge → Origin (US-East): "GET /app.a1b2c3.js" Origin → Edge: 200 OK + content + Cache-Control headers Edge: stores in cache (respecting max-age / s-maxage) Edge → User: 200 OK + content Time: ~220ms (edge-to-origin round trip + origin processing) Next request from ANY user in Mumbai region: cache HIT (~10ms) ── Cache STALE (revalidation) ───────────────────── User (Delhi) → Edge (Mumbai): "GET /api/products" Edge cache: ⚠️ Found but expired Edge → Origin: "GET /api/products" + If-None-Match: "abc123" Origin → Edge: 304 Not Modified (content unchanged) Edge: refreshes cache TTL Edge → User: 200 OK + cached content Time: ~210ms (but no body transferred from origin)
Anycast routing
CDNs use Anycast — a networking technique where the same IP address is announced from multiple locations. When a user resolves the CDN's IP, the internet's routing protocol (BGP) automatically directs them to the nearest edge server. No special client-side logic needed.
Key Concepts
These are the core terms you need to know for interviews and system design discussions. Each one maps to a specific part of how CDNs operate.
Edge Server
A CDN server located close to end users. Caches content and serves it directly. Major CDNs have hundreds of edge locations worldwide. Also called a PoP (Point of Presence).
Origin Server
Your actual backend server where the content originates. The CDN fetches from the origin on cache misses. The origin handles dynamic logic, databases, and authentication.
Cache Hit vs Cache Miss
A cache hit means the edge has a fresh copy — served in <20ms. A cache miss means the edge must fetch from origin — 100-300ms. Cache hit ratio is the key CDN metric (aim for 90%+).
TTL (Time to Live)
How long the edge server keeps a cached copy before considering it stale. Controlled by Cache-Control: max-age or s-maxage headers from the origin. Longer TTL = more cache hits, but slower updates.
| Concept | What It Is | Why It Matters |
|---|---|---|
| PoP (Point of Presence) | A physical CDN location with edge servers | More PoPs = more users served from nearby locations |
| Cache Hit Ratio | % of requests served from cache vs origin | Higher ratio = faster site, lower origin load. Target: 90%+ |
| Origin Shield | An intermediate CDN cache between edges and origin | Reduces origin load — edges fetch from shield, not origin directly |
| Cache Invalidation / Purge | Forcing the CDN to discard cached content | Needed when you deploy updates and can't wait for TTL to expire |
| Anycast | Same IP address served from multiple locations | Automatically routes users to the nearest edge server |
Origin shield
Without an origin shield, if 100 edge servers all have a cache miss at the same time, your origin gets 100 simultaneous requests for the same resource. An origin shield is a single intermediate cache — all edges fetch from the shield, and only the shield fetches from origin. This collapses 100 requests into 1.
What Gets Cached?
Not everything should be cached on a CDN. The general rule: cache content that is the same for all users and changes infrequently. Avoid caching user-specific or rapidly changing content on shared caches.
| Resource | CDN Cacheable? | Typical TTL | Notes |
|---|---|---|---|
| JavaScript bundles | Yes (ideal) | 1 year (fingerprinted) | Fingerprinted filenames (app.a1b2c3.js) — cache forever |
| CSS files | Yes (ideal) | 1 year (fingerprinted) | Same strategy as JS — content hash in filename |
| Images / videos | Yes (ideal) | 1 day – 1 year | Product images, logos, hero images. Large files benefit most. |
| Fonts | Yes (ideal) | 1 year | Fonts rarely change. Cache aggressively. |
| HTML pages | Sometimes | 0 – 5 min | Static/marketing pages: yes. Dynamic/personalized: no. |
| Public API responses | Sometimes | 1 – 60 min | Product listings, search results. Use s-maxage + stale-while-revalidate. |
| User-specific API data | No | N/A | Account info, cart, dashboard. Use Cache-Control: private. |
| Authentication endpoints | No | N/A | Login, token refresh. Must always hit origin. Use no-store. |
Is the content the same for ALL users? │ ├─ YES → Is it a static asset (JS/CSS/image/font)? │ │ │ ├─ YES → Cache forever with fingerprinted filename │ │ Cache-Control: public, max-age=31536000, immutable │ │ │ └─ NO → Is it acceptable to be slightly stale? │ │ │ ├─ YES → Short CDN cache with revalidation │ │ Cache-Control: public, s-maxage=300, stale-while-revalidate=60 │ │ │ └─ NO → Don't cache on CDN, revalidate every time │ Cache-Control: public, no-cache │ └─ NO → Don't cache on CDN Cache-Control: private (browser cache only) Or: no-store (for sensitive data)
The 80/20 rule
Static assets (JS, CSS, images, fonts) typically account for 80-90% of a page's bytes and are perfectly cacheable. Just caching these on a CDN gives you most of the performance benefit with zero risk of serving stale dynamic data.
Benefits of CDN
CDNs provide benefits beyond just speed. They fundamentally change the scalability and reliability characteristics of your application.
Reduced Latency
Content served from 10-30ms away instead of 100-300ms. Users experience near-instant page loads for cached resources. The biggest and most direct benefit.
Reduced Origin Load
With a 95% cache hit ratio, your origin handles 5% of traffic. A site with 1M requests/day sends only 50K to origin. This means smaller, cheaper servers.
Global Scalability
CDN edges handle traffic spikes automatically. A viral post that sends 10x traffic doesn't overwhelm your origin — the CDN absorbs it from cache.
DDoS Protection
CDN networks absorb distributed attacks across their global infrastructure. Malicious traffic is filtered at the edge before reaching your origin.
Improved Core Web Vitals
Faster resource delivery directly improves FCP (First Contentful Paint) and LCP (Largest Contentful Paint) — key metrics for SEO and user experience.
Bandwidth Savings
CDN bandwidth is typically cheaper than origin bandwidth. Plus, CDNs handle compression (gzip/Brotli) at the edge, reducing transfer sizes by 60-80%.
| Metric | Without CDN | With CDN |
|---|---|---|
| Latency (distant user) | 200-300ms | 10-30ms |
| Origin server requests | 100% of traffic | 5-10% of traffic |
| Traffic spike handling | Origin overloaded | CDN absorbs from cache |
| Global performance | Fast near server, slow elsewhere | Fast everywhere |
Real-World Example
Let's trace what happens when a user in Tokyo loads an e-commerce product page — with and without a CDN. The origin server is in US-East (Virginia).
❌ Without CDN
Round trip Tokyo → Virginia: ~180ms GET /products/shoes (HTML) → Origin → 180ms RTT + 30ms server = 210ms GET /app.a1b2c3.js (150KB) → Origin → 180ms RTT + 5ms = 185ms GET /styles.d4e5.css (40KB) → Origin → 180ms RTT + 3ms = 183ms GET /hero.jpg (200KB) → Origin → 180ms RTT + 8ms = 188ms GET /logo.png (15KB) → Origin → 180ms RTT + 2ms = 182ms GET /fonts/inter.woff2 (35KB) → Origin → 180ms RTT + 2ms = 182ms With HTTP/2 multiplexing (parallel on 1 connection): TCP + TLS setup: ~360ms (2 round trips) All resources: ~210ms (limited by slowest) Total time to first paint: ~570ms Total data: 440KB from Virginia
✅ With CDN (edge in Tokyo)
Round trip Tokyo → Tokyo edge: ~8ms GET /products/shoes (HTML) → Edge (no-cache) → revalidate with origin Edge → Origin: 180ms + 304 response Total: ~190ms (still needs origin for HTML) GET /app.a1b2c3.js (150KB) → Edge CACHE HIT → 8ms ✅ GET /styles.d4e5.css (40KB) → Edge CACHE HIT → 8ms ✅ GET /hero.jpg (200KB) → Edge CACHE HIT → 8ms ✅ GET /logo.png (15KB) → Edge CACHE HIT → 8ms ✅ GET /fonts/inter.woff2 (35KB) → Edge CACHE HIT → 8ms ✅ With HTTP/2 multiplexing: TCP + TLS to edge: ~16ms (2 round trips × 8ms) HTML (revalidated): ~190ms Static assets (cached): ~8ms (parallel, all from edge) Total time to first paint: ~210ms Improvement: 63% faster (570ms → 210ms) Origin requests: 1 (HTML only) instead of 6
| Metric | Without CDN | With CDN | Improvement |
|---|---|---|---|
| Time to first paint | ~570ms | ~210ms | 63% faster |
| Origin requests | 6 | 1 | 83% reduction |
| Data from origin | 440KB | ~0.5KB (304) | 99.9% reduction |
| Connection setup | ~360ms | ~16ms | 95% faster |
The HTML bottleneck
Even with a CDN, the HTML page often needs to hit the origin (using no-cache + ETag) because it references the latest asset filenames. This is the one request that can't be fully eliminated. Some teams cache HTML on the CDN with short TTLs (5-60s) to avoid even this round trip for most users.
CDN + HTTP Caching
CDNs don't have their own caching rules — they respect the HTTP caching headers your origin server sends. The same Cache-Control headers that control browser caching also control CDN caching, with a few CDN-specific additions.
Headers That Control CDN Behavior
| Header | Effect on CDN | Example |
|---|---|---|
Cache-Control: public | CDN is allowed to cache this response | Static assets, public pages |
Cache-Control: private | CDN must NOT cache — browser only | User-specific data, authenticated responses |
s-maxage=N | CDN cache duration (overrides max-age for CDN) | max-age=60, s-maxage=3600 → CDN caches 1hr, browser 1min |
Vary: Accept-Encoding | CDN stores separate versions per encoding | gzip version and brotli version cached separately |
Cache-Control: no-store | CDN must not cache at all | Sensitive data, authentication endpoints |
Surrogate-Control | CDN-specific header (stripped before reaching browser) | Some CDNs support this for CDN-only cache rules |
Cache Busting with Fingerprinted URLs
The problem: You deploy new code, but CDN edges worldwide still serve the old cached version until TTL expires. Users see stale content. The solution: fingerprinted filenames Old: /app.js → CDN caches, can't invalidate easily New: /app.a1b2c3.js → URL changes when content changes How it works: 1. Build tool generates content hash: app.a1b2c3.js 2. HTML references the hashed filename 3. CDN sees a NEW URL → fetches from origin (cache miss) 4. Old URL (/app.x9y8z7.js) is never requested again 5. No need to purge CDN cache — the old URL just expires naturally Cache-Control: public, max-age=31536000, immutable ↑ Safe because the URL itself is the version identifier This is why you always revalidate HTML (no-cache): HTML is the entry point that references asset filenames. If HTML is cached with a long TTL, it points to old filenames even after you deploy new assets.
s-maxage is your friend
Use s-maxage to set different cache durations for CDN vs browser. Example: max-age=60, s-maxage=3600 — the browser revalidates after 1 minute, but the CDN caches for 1 hour. This reduces origin load while keeping browser caches relatively fresh.
Performance Insights
A CDN is one of the highest-ROI performance investments. Here are the specific techniques and their measurable impact.
Serve Static Assets from CDN
Move JS, CSS, images, and fonts to a CDN with long cache TTLs. This alone reduces load times by 50-70% for users far from your origin. The single most impactful CDN optimization.
Enable Compression at the Edge
CDNs can compress responses with gzip or Brotli at the edge, reducing transfer sizes by 60-80%. Brotli compresses ~15-20% better than gzip. Most CDNs handle this automatically.
Use Origin Shield
Configure an origin shield to collapse cache misses from multiple edges into a single origin request. Reduces origin load by 80-90% during cache miss storms (e.g., after a deploy).
Optimize Cache Hit Ratio
Target 90%+ cache hit ratio. Monitor via CDN analytics. Low hit ratio means wrong TTLs, too many URL variations (query strings), or Vary headers creating too many cache keys.
Edge Compute (SSR at the Edge)
Modern CDNs (Cloudflare Workers, Vercel Edge Functions) can run code at the edge — enabling server-side rendering close to users. Eliminates the origin round trip even for dynamic HTML.
Image Optimization at the Edge
CDNs like Cloudflare Images and Vercel Image Optimization can resize, compress, and convert images (to WebP/AVIF) at the edge. Serve the optimal format and size per device automatically.
Measure your cache hit ratio
Most CDN dashboards show cache hit ratio. If it's below 80%, investigate: are query strings creating unique cache keys? Are TTLs too short? Is Vary creating too many variants? Every 1% improvement in hit ratio means fewer origin requests and faster responses.
Common Mistakes
Not using a CDN for static assets
Serving JS, CSS, images, and fonts directly from your origin server means every user worldwide pays the full latency cost. A user in Tokyo waits 200ms+ for each resource from a US server.
✅Put all static assets behind a CDN. Most hosting platforms (Vercel, Netlify, AWS) include CDN by default. For custom setups, use CloudFront, Cloudflare, or Fastly in front of your origin.
Setting TTLs too short on static assets
Using max-age=300 (5 minutes) on fingerprinted JS/CSS means the CDN re-fetches from origin every 5 minutes — even though the content hasn't changed. This wastes origin bandwidth and reduces cache hit ratio.
✅Fingerprinted assets (app.a1b2c3.js) should use max-age=31536000 (1 year) with immutable. The URL changes when content changes, so long TTLs are safe. Reserve short TTLs for content that actually changes.
Caching user-specific responses on CDN
Using Cache-Control: public on API responses that contain user-specific data (account info, cart contents) means the CDN serves User A's data to User B. A serious security and correctness bug.
✅Always use Cache-Control: private for user-specific responses. This restricts caching to the browser only. For pages with mixed content, load the public shell from CDN and fetch user data via separate private API calls.
Not invalidating cache after deploys
Deploying new code but not purging the CDN cache means users get old cached versions until TTL expires. If you use non-fingerprinted URLs with long TTLs, users may be stuck for hours or days.
✅Use fingerprinted filenames (automatic cache busting) so you never need to purge. If you must use non-fingerprinted URLs, use short TTLs or trigger a CDN purge as part of your deploy pipeline.
Query strings breaking cache keys
URLs like /app.js?v=1.2.3 and /app.js?v=1.2.4 are different cache keys on most CDNs. If analytics tools or tracking scripts append random query params, each variation is a cache miss.
✅Configure your CDN to ignore query strings for static assets, or use filename-based versioning (app.a1b2c3.js) instead of query-string versioning. Check CDN docs for cache key configuration.
Interview Questions
Q:What is a CDN and how does it improve performance?
A: A CDN is a globally distributed network of edge servers that cache and serve content from locations close to users. Instead of every request traveling to a single origin server (100-300ms), the CDN serves cached copies from the nearest edge (5-20ms). This reduces latency by 80-95%, decreases origin server load, and improves scalability. CDNs are most effective for static assets (JS, CSS, images, fonts) that are the same for all users.
Q:What is the difference between a cache hit and a cache miss?
A: A cache hit occurs when the CDN edge server has a fresh cached copy of the requested resource — it serves it directly without contacting the origin (~5-20ms). A cache miss occurs when the edge doesn't have the resource or the cache has expired — it must fetch from the origin server (~100-300ms), then caches the response for future requests. Cache hit ratio (hits / total requests) is the key CDN performance metric — aim for 90%+.
Q:How does a CDN decide which edge server to route a request to?
A: CDNs use Anycast routing — the same IP address is announced from multiple edge locations worldwide. When a user's DNS query resolves the CDN domain, the internet's BGP routing protocol automatically directs the request to the nearest (lowest-latency) edge server. This happens at the network level with no client-side logic needed. Some CDNs also use DNS-based routing with geolocation.
Q:How do you handle cache invalidation on a CDN?
A: The best approach is fingerprinted filenames (app.a1b2c3.js) — the URL changes when content changes, so old cached versions are never requested again. No purge needed. For non-fingerprinted URLs, options include: (1) CDN purge API to clear specific URLs or patterns, (2) short TTLs so caches expire quickly, (3) versioned query strings (/api/data?v=2). Cache invalidation is one of the hardest problems in computing — fingerprinting avoids it entirely.
Q:What is an origin shield and when would you use it?
A: An origin shield is an intermediate CDN cache layer between edge servers and the origin. Without it, a cache miss on 100 edge servers simultaneously sends 100 requests to your origin. With an origin shield, all edges fetch from the shield, and only the shield fetches from origin — collapsing 100 requests into 1. Use it when your origin is sensitive to traffic spikes, especially after deploys when all edge caches are cold.
Q:How does Cache-Control: s-maxage work with CDNs?
A: s-maxage sets the cache duration specifically for shared caches (CDN, proxy) and overrides max-age for those caches. Example: max-age=60, s-maxage=3600 means the browser cache expires after 1 minute, but the CDN caches for 1 hour. This lets you keep browser caches fresh (users see recent data) while reducing origin load (CDN serves most requests from its longer cache).
Q:When should you NOT use a CDN?
A: Don't cache on CDN: (1) User-specific data (account info, cart, dashboard) — use Cache-Control: private. (2) Sensitive data (bank statements, medical records) — use no-store. (3) Real-time data that must be fresh on every request (stock prices, live scores) — bypass CDN or use very short TTLs. (4) POST/PUT/DELETE requests — these modify data and should always reach the origin. CDNs are for read-heavy, cacheable content.
Q:How would you design a CDN strategy for a global e-commerce site?
A: Three tiers: (1) Static assets (JS, CSS, fonts, product images) — fingerprinted filenames, Cache-Control: public, max-age=31536000, immutable. Served from CDN edge worldwide. (2) HTML pages — Cache-Control: no-cache with ETag on CDN. Always revalidated but 304 saves bandwidth. (3) API responses — public product data cached on CDN with s-maxage=300, stale-while-revalidate=60. User-specific data (cart, account) bypasses CDN with Cache-Control: private.
Practice Section
The Slow International Users
Your analytics show that users in Europe and Asia experience 3x slower page loads than US users. Your origin server is in US-East. All static assets are served directly from the origin. How would you fix this?
Answer: Deploy a CDN (Cloudflare, CloudFront, or Fastly) in front of your origin. Configure fingerprinted static assets with Cache-Control: public, max-age=31536000, immutable. After the first request populates edge caches, European and Asian users get assets from nearby edges in 10-30ms instead of 200-300ms from US-East. Expected improvement: 50-70% faster page loads for international users.
The Post-Deploy Cache Problem
After deploying new code, some users see the old version of your app for hours. Your JS bundle is served as /bundle.js with Cache-Control: public, max-age=86400 on the CDN. What's wrong and how do you fix it?
Answer: The filename doesn't change on deploy, so CDN edges serve the cached old version for 24 hours. Fix: use fingerprinted filenames (bundle.a1b2c3.js) so the URL changes on every deploy. Set max-age=31536000 with immutable on hashed files. Always revalidate HTML (no-cache + ETag) so it picks up new asset filenames immediately. This eliminates the need for CDN purges entirely.
The Low Cache Hit Ratio
Your CDN dashboard shows a 40% cache hit ratio — far below the 90%+ target. Your static assets have proper long TTLs. What could be causing so many cache misses, and how would you investigate?
Answer: Common causes: (1) Query strings creating unique cache keys — analytics params like ?utm_source=x make each URL unique. Configure CDN to ignore query strings for static assets. (2) Vary: Cookie header creating per-user cache entries. (3) Too many URL variations for the same content. (4) Low-traffic edges where content expires before being requested again. Check CDN logs for cache miss reasons and unique cache key counts.
The CDN Security Leak
A security audit reveals that your CDN is caching and serving user-specific API responses. User A's account data was served to User B from the CDN cache. How did this happen and how do you prevent it?
Answer: The API response was sent with Cache-Control: public (or no Cache-Control header, letting the CDN use default caching). The CDN cached User A's response and served it to User B requesting the same URL. Fix: set Cache-Control: private on all user-specific API responses so CDNs never cache them. For sensitive data, use no-store. Audit all API endpoints to ensure proper cache headers. Add Vary: Authorization if responses differ by auth token.
The Global Scalability Design
You're designing the frontend delivery architecture for a news website that serves 50 million page views per day across 30 countries. How would you use CDNs to handle this scale?
Answer: Use a multi-tier CDN strategy: (1) All static assets (JS, CSS, images) fingerprinted and cached forever on CDN edges globally. (2) Article HTML pages cached on CDN with s-maxage=300, stale-while-revalidate=60 — most readers see cached version, origin only handles cache misses. (3) Origin shield to protect the origin from cache miss storms. (4) Image optimization at the edge (WebP/AVIF conversion, responsive sizing). At 50M views/day with 95% cache hit ratio, origin handles only 2.5M requests — manageable with modest infrastructure.
Cheat Sheet
Quick Revision Cheat Sheet
CDN: A globally distributed network of edge servers that cache and serve content from locations close to users. Reduces latency from 200ms+ to 10-30ms.
Edge Server: A CDN server near end users. Caches content and serves it directly. Also called a PoP (Point of Presence). Major CDNs have 100-4000+ edge locations.
Origin Server: Your actual backend server. The CDN fetches from origin on cache misses. Handles dynamic logic, databases, and authentication.
Cache Hit vs Miss: Hit: edge has fresh copy, serves in <20ms, origin not contacted. Miss: edge fetches from origin, 100-300ms. Target 90%+ hit ratio.
TTL (Time to Live): How long the edge keeps a cached copy. Controlled by Cache-Control: max-age or s-maxage. Longer TTL = more hits but slower updates.
s-maxage: Cache duration for CDN only (overrides max-age for shared caches). Use to cache longer on CDN than in browser: max-age=60, s-maxage=3600.
Origin Shield: Intermediate cache between edges and origin. Collapses multiple edge cache misses into a single origin request. Protects origin from traffic spikes.
Cache Busting: Fingerprinted filenames (app.a1b2c3.js) change the URL when content changes. No CDN purge needed — old URLs expire naturally. Always revalidate HTML.
What to Cache on CDN: Static assets (JS, CSS, images, fonts) — cache forever. Public HTML — short TTL or no-cache. Public API data — short s-maxage. User-specific data — never (private).
Anycast Routing: Same IP announced from multiple locations. BGP routing directs users to the nearest edge automatically. No client-side logic needed.
Key Benefits: Reduced latency (80-95%), reduced origin load (90%+), global scalability, DDoS protection, improved Core Web Vitals (FCP, LCP), bandwidth savings.
When NOT to Use CDN: User-specific data (private), sensitive data (no-store), real-time data, write operations (POST/PUT/DELETE). CDNs are for read-heavy, cacheable content.