CDN: The 'Local Convenience Store' Mental Model
Why does your image load instantly for users in the US but crawls in Vietnam? A mastery guide to CDN Edge Nodes, Cache-Control headers, and cache busting.
Your product photos are hosted on a server in Frankfurt. A user in Hanoi clicks your website. That image has to physically travel 9,000 km of fiber optic cable underwater before it appears on their screen.
Physics is the bottleneck. You cannot make light move faster.
But you can move the content closer to the user. This is a CDN.
This is the Mastery Guide to Content Delivery Networks — from the mental model to Cache-Control headers to cache busting.
Part 1: Foundations (The Mental Model)
The Origin Server = The Main Factory
Your server in Frankfurt is the Main Factory. It produces everything: your app, your images, your videos, your CSS files.
The problem: your factory is far away. Shipping from Frankfurt to Hanoi takes time (150–300ms round-trip just for the network alone).
The CDN Edge Node = The Local 7-Eleven
A CDN (like Cloudflare or AWS CloudFront) operates hundreds of Edge Nodes — servers placed in cities around the world.
Think of each Edge Node as a local 7-Eleven convenience store. It doesn’t produce anything; it just stocks the most popular items from the Main Factory nearby.
User in Hanoi
│
▼
CDN Edge (Singapore) ← Stocks copy of your images/assets
│ (10ms away)
│ if not cached yet ↓
└──────────────────► Origin Server (Frankfurt)
(300ms away — only for first request!)
The Key Insight: The first user in each region hits the origin. Every subsequent user in that region gets served from the local Edge Node. The origin server is only called once per region per file.
Part 2: The Investigation (What Gets Cached)
Not everything should be on a CDN. Only static, infrequently-changing content.
| Should CDN Cache? | Examples | Why |
|---|---|---|
| ✅ Yes | Images, CSS, JS bundles, Fonts, Videos | Same file for every user. |
| ✅ Yes | Publicly-accessible API responses | Same JSON for every user. |
| ❌ No | User-specific pages (/dashboard) | Different per user. |
| ❌ No | Authentication endpoints (/login) | Cannot be cached! |
| ❌ No | Real-time data (/stock-price) | Changes every second. |
The Cache-Control Header
You instruct the CDN (and the browser) how long to cache a file using the Cache-Control HTTP response header.
Cache-Control: public, max-age=31536000, immutable
public: “Intermediaries (CDN) can cache this.”max-age=31536000: “Cache for 1 year (in seconds).”immutable: “This file will NEVER change. Don’t even bother checking for updates.”
The Golden Rule for Static Assets: Use long TTLs + cache busting via filename hashing.
Part 3: The Diagnosis (Cache Busting — “My Update Isn’t Showing!”)
You uploaded a new logo.png. But users keep seeing the old one for days because the CDN cached it.
This is the #1 CDN frustration. The fix is Cache Busting.
The Wrong Way (Purging)
You manually go to Cloudflare and click “Purge Cache” every time you deploy. This is:
- Easy to forget.
- Only clears the CDN; the browser might still have it cached.
The Right Way (Content Hashing)
Name your files with a hash of their content. When the content changes, the filename changes. Caches are busted automatically.
# Old file:
logo.abc123.png → Cache-Control: max-age=31536000
# You update the logo. Build tool detects change.
logo.def456.png → New URL! CDN & browsers see this as a BRAND NEW file.
Modern build tools (Vite, Webpack) do this automatically. Your <img src="logo.abc123.png" alt="" loading="lazy" decoding="async" /> becomes <img src="logo.def456.png" alt="" loading="lazy" decoding="async" /> after every build where the file changes.
Part 4: The Resolution (Setup Patterns)
1. Cloudflare (Simplest Setup)
Change your DNS to point to Cloudflare. Every HTTP request passes through their global network automatically. Static assets are cached at the edge.
Pro tip: Set a Page Rule to cache everything with a long TTL for your static assets path.
2. AWS CloudFront + S3
Host static assets in S3. Put CloudFront in front of it.
User → CloudFront (Edge) → S3 (Origin)
Correct Cache-Control header in S3: When you upload a file, set the metadata:
Cache-Control: public, max-age=31536000
3. Nginx as a “Mini CDN” for your origin
Cache responses at your Nginx layer before they hit your app:
proxy_cache_path /tmp/nginx_cache levels=1:2
keys_zone=my_cache:10m max_size=1g;
server {
location /static/ {
proxy_cache my_cache;
proxy_cache_valid 200 1y; # Cache 200 responses for 1 year
add_header X-Cache-Status $upstream_cache_status; # HIT or MISS
proxy_pass http://backend;
}
}
Final Mental Model
CDN Edge Node -> The local 7-Eleven. (Nearby, fast, stocks popular items).
Origin Server -> The Main Factory. (Far, authoritative, visited rarely).
Cache-Control: max-age=31536000 -> "Keep this for exactly 1 year."
Content Hashing (logo.abc123.png) -> "New filename = cache busted automatically."
X-Cache-Status: HIT -> "Served from Edge. User is happy."
X-Cache-Status: MISS -> "Served from Origin. User waited."
Rules:
- If it’s the same for every user → put it on a CDN.
- If it changes → use content hashing, not manual purging.
- If it’s private → never put it on a CDN.
Related posts
-
Caching & Redis: The 'Sticky Note' Mental Model
Why does Redis make everything faster? A mastery guide to cache invalidation (the hardest problem in CS), eviction strategies, and Redis data types.
-
Latency vs. Throughput: The 'Water Pipe' Mental Model
Why is your API slow even though your internet is fast? A mastery guide to P99 latency, bandwidth, and finding the bottleneck.
-
Load Balancer, Reverse Proxy, API Gateway: The Grand Hotel Mental Model
Confused by the 'Traffic Trio'? A mastery-level guide to Load Balancers, Reverse Proxies, and API Gateways — from mental models to Nginx configs.
-
Database Indexing: The 'Library Card Catalog' Mental Model
Why does adding an index make a query 100x faster? A mastery guide to B-Trees, compound indexes, covering indexes, and the queries that kill your database.