CDN
In the previous page, we made ShortLink's app servers grow and shrink by themselves. But every user still reaches back to our data centers, even for files that never change. In this page, we move those files closer to the user with a CDN.
Definition
A CDN (Content Delivery Network) is a group of servers spread across the world that keep copies of your content close to users.
Instead of every user fetching a file from our main server, they get it from a nearby copy.
Analogy: a book publisher has one big warehouse. Shipping every book from there takes days. So the publisher keeps copies in shops in every city. You pick up your book from the shop near you.
1Without CDN: User in India → Origin server in US (far, slow)2With CDN: User in India → CDN server in India (near, fast)Our main server is called the origin. It holds the original files. The CDN servers hold copies.
Let's see why we need this.
Need for CDN
Here is what breaks. ShortLink has a landing page with a logo, CSS, JavaScript, and images. The whole page is about 2 MB. The origin is in the US. A user in India opens it.
1Distance: about 13,000 km2Round trip: about 250 ms for each request3Files on the page: about 20 files4Many files load in parallel, but each still pays the long trip ✗Distance is only one problem. Look at the load on the origin:
11,000,000 page views per day2Each page view = 2 MB of files3 4Data sent by origin: 1,000,000 × 2 MB = 2,000,000 MB = 2 TB per dayOur servers spend most of their time sending the same files again and again. That wastes CPU and network, and the bandwidth bill is large.
A CDN fixes both problems:
- Lower latency. Files come from a nearby server.
- Less load on the origin. The origin sends each file to the CDN once, not to every user.
- Handles spikes. A viral moment hits the CDN's many servers, not our few.
- Lower cost. Less data leaves our own servers.
Next, let's follow one request.
How a CDN Works
A user in India opens sl.io/logo.png. The first time, the CDN does not have the file yet:
11. User asks DNS "Where is sl.io?"22. DNS answers address of the nearest CDN server33. User → CDN server "GET /logo.png"44. CDN server checks "Do I have logo.png saved?" → No55. CDN server → Origin "Please send logo.png"66. Origin → CDN server sends the file77. CDN server saves a copy and sends the file to the userNow the next user in India asks for the same file:
11. User → CDN server "GET /logo.png"22. CDN server checks "Do I have logo.png saved?" → Yes33. CDN server → User sends the saved copy, origin is not involved ✓Only the first request pays the long trip. Everyone after that gets a fast answer.
1Users → CDN Edge Server → (only on first request) → OriginLet's see where these CDN servers actually sit.
Edge Servers and Points of Presence
An edge server is a CDN server that sits close to users, at the "edge" of the network. A Point of Presence (PoP) is a location that holds a group of edge servers, usually inside or near an internet provider's building.
Big CDNs have hundreds of PoPs in many cities.
1 ┌→ PoP: Mumbai2Origin (US) ───────→├→ PoP: London3 ├→ PoP: Singapore4 └→ PoP: New YorkEach PoP keeps its own copies. Mumbai may have a file that London does not, because nobody in London has asked for it yet.
Some CDNs add a middle layer. Edge servers ask a bigger regional cache first, and only that cache asks the origin. This protects the origin when many PoPs miss at the same time.
1User → Edge (PoP) → Regional Cache → OriginNow, what exactly gets copied?
What a CDN Caches
A CDN works best for content that is the same for every user and does not change often.
| Content | Example in ShortLink | CDN friendly? |
|---|---|---|
| Static files | Logo, CSS, JavaScript, images | Yes, cached for a long time |
| Public pages | Landing page, docs | Yes, with a short TTL |
| Redirects | sl.io/abc123 → long link | Sometimes, if the link rarely changes |
| Private or live data | Dashboard, login, create link | No, always goes to the origin |
Here is what breaks if we cache the wrong thing. Say the CDN saves Alice's dashboard page. Bob asks for the dashboard, and the CDN sends him Alice's saved page. Bob sees Alice's private links ✗
So the rule is simple: cache what is the same for everyone. Never cache what is personal.
Redirects deserve a closer look because ShortLink is read-heavy. A CDN can serve sl.io/abc123 straight from the edge, so the origin is not touched at all. The catch: if the CDN answers, our servers never see the click. Click counts for analytics would be lost unless the CDN sends us its logs. Also, if someone edits the link, the CDN may keep sending the old target until the saved copy expires.
Next, let's measure how well the CDN is doing.
Cache Hit and Cache Miss
- Cache hit: the CDN has the file and sends it. Fast.
- Cache miss: the CDN does not have the file, so it fetches it from the origin. Slow.
The hit ratio is the share of requests that are hits:
1hit ratio = hits / total requestsHere is the math for ShortLink. Say a hit takes 20 ms, and a miss takes 270 ms (20 ms to the edge plus 250 ms to the origin).
1Hit ratio 95%:2Average latency = 0.95 × 20 + 0.05 × 2703 = 19 + 13.54 = 32.5 ms5 6Hit ratio 50%:7Average latency = 0.50 × 20 + 0.50 × 2708 = 10 + 1359 = 145 msThe hit ratio changes everything. And look at the origin load:
11,000,000 page views × 2 MB = 2 TB per day2 3Hit ratio 95% → origin sends 5% = 100 GB per day4Hit ratio 50% → origin sends 50% = 1 TB per dayWhat lowers the hit ratio?
- Short TTL. Copies expire too quickly.
- Many different URLs for the same file. For example
logo.png?user=1andlogo.png?user=2look like two files, so each is a miss. - Rarely requested files. Copies expire before anyone asks again.
- Personal content. It cannot be cached at all.
So how do files get into the CDN in the first place?
Push vs. Pull CDN
There are two ways to fill a CDN.
Pull CDN. The CDN fetches a file from the origin the first time a user asks for it. This is what we saw in the request flow above.
Push CDN. We upload files to the CDN ahead of time. The CDN holds them before any user asks.
1Pull: User asks → CDN misses → CDN fetches from origin → CDN saves2Push: We upload → CDN saves → User asks → CDN hits right away| Pull CDN | Push CDN | |
|---|---|---|
| Who copies the file | The CDN, on first request | We, before users ask |
| First user | Slow (a miss) | Fast (already there) |
| Effort | Very low, works automatically | More work: we must upload and remove files |
| Storage | Only files people actually use | All files we pushed, used or not |
| Updates | Copy refreshes after it expires | We push the new version |
| Best for | Websites with many files and changing traffic | Large files and planned launches, like a big video |
Most websites, ShortLink included, use pull. It is simple and needs no upload step. Use push when the first request must also be fast, or when files are huge and you know when they will be needed.
Now, how long does the CDN keep a copy?
Cache Control and TTL
The origin tells the CDN how long to keep a file. It does this with a response header called Cache-Control. A header is a small piece of extra information sent along with a file.
The time is the TTL (Time To Live): how many seconds a copy stays fresh.
| Header value | Plain meaning |
|---|---|
max-age=86400 | Keep this copy for 86,400 seconds (1 day) |
public | Any cache may save it, including the CDN |
private | Only the user's own browser may save it, not the CDN |
no-store | Do not save it anywhere |
no-cache | You may save it, but ask the origin before using it |
Here is how ShortLink would set headers in Java:
import org.springframework.http.CacheControl;import org.springframework.http.ResponseEntity;import java.time.Duration;public class AssetController {// Logo: same for everyone, rarely changes → cache for 1 daypublic ResponseEntity<byte[]> logo(byte[] logoBytes) {return ResponseEntity.ok().cacheControl(CacheControl.maxAge(Duration.ofDays(1)).cachePublic()).body(logoBytes);}// Dashboard: personal data → never let the CDN save itpublic ResponseEntity<String> dashboard(String html) {return ResponseEntity.ok().cacheControl(CacheControl.noStore()).body(html);}}
Choosing a TTL is a trade-off:
| Long TTL (days) | Short TTL (seconds) | |
|---|---|---|
| Hit ratio | High | Low |
| Origin load | Low | High |
| Speed for users | Fast | Slower on more requests |
| Stale content risk | High (old file stays long) | Low |
| Choose it when | File rarely changes, like a logo | Content changes often, like a news page |
But a long TTL creates a new problem. What if we change the file before the TTL ends?
Cache Invalidation in CDN
Here is what breaks. We update style.css to fix a bug. But the CDN saved the old copy with a TTL of 1 day. For up to 24 hours, many users still get the old file ✗
Cache invalidation means removing or replacing saved copies before they expire. There are three common ways:
- Purge. We tell the CDN "delete this file now". It fetches the new one on the next request. Simple, but it can take seconds to minutes to reach every PoP, and a big purge makes many misses at once.
- Versioned file names. Put a version in the name:
style.v1.cssbecomesstyle.v2.css. The new name is a new file for the CDN, so there is no old copy. This is the most reliable way for static files. - Short TTL. Accept that content is at most a few seconds old.
1Before: page links to style.v1.css (CDN has it, TTL 1 year)2Update: page links to style.v2.css (CDN has never seen it → fetches from origin)3Old v1 copies are simply never requested again ✓Versioned names let us use a very long TTL (even a year) with no risk of stale files. Only the HTML page that links to them needs a short TTL.
Invalidation is a big topic, and we cover it fully in the Cache Invalidation page. Next, let's see how a user finds the nearest CDN server.
CDN Routing (DNS and Anycast)
The CDN must send each user to a nearby, healthy edge server. It uses the same ideas we saw in the global load balancer page:
- DNS-based routing. When the user looks up the name, the CDN's DNS answers with the address of the closest PoP.
- Anycast. Many PoPs share one IP address. The internet's own routing sends each user to the closest one. It reacts faster because it does not depend on cached DNS answers.
1DNS routing: User → DNS → "use Mumbai PoP" → User → Mumbai PoP2Anycast: User → shared IP → internet routes to nearest PoPIf a PoP fails, the CDN stops sending users there, and they move to the next closest one. Users notice nothing.
In practice, ShortLink does not build any of this. We use a CDN provider such as Cloudflare, Amazon CloudFront, or Akamai, point our domain at it, and set our headers.
So what do we pay for all this?
Limitations and Trade-offs of CDN
1. Stale content. A copy may be old until it expires or is purged.
2. The first request is slow. A cache miss pays the full trip to the origin. For a rare file, many users may be "first".
3. Wrong caching is dangerous. Caching a personal page can show one user's data to another. Header mistakes are the most common cause.
4. Not useful for live or personal data. Dashboards, login, and "create link" must reach the origin every time.
5. Cost. CDNs charge for data sent and sometimes for requests. A big viral file can raise the bill.
6. Less visibility. If the CDN answers, our servers never see the request. Logs and analytics need extra setup.
7. A new part that can fail. Many sites depend on one CDN provider. If it has an outage, the site can be hard to reach.
8. Origin still needed. The CDN does not replace the origin. After a purge or for new files, the origin must still handle a rush of misses.
| You gain | You pay |
|---|---|
| Fast loading for users everywhere | Risk of stale or wrongly shared content |
| Much less load on the origin | Cost based on traffic |
| Handles spikes easily | Less direct view of requests |
| Lower bandwidth cost at the origin | Another provider to depend on |
Finally, let's clear up a common confusion.
CDN vs. Global Load Balancer vs. Origin Server
All three can send a user to a nearby place, so people mix them up. They do different jobs.
- Origin server: where the real content and logic live. It creates the answer.
- CDN: keeps saved copies of content near users. It does not create anything new.
- Global load balancer: sends each user to the best data center, where real servers run and compute answers.
Analogy: a CDN is a shop that sells copies of a book. A global load balancer is a signpost that sends you to the nearest publisher's office, where a person can write you a custom letter.
1Static file: User → CDN edge → (miss only) → Origin2Dynamic call: User → Global LB → nearest Data Center → Load Balancer → App Server| Origin server | CDN | Global load balancer | |
|---|---|---|---|
| Main job | Create the real answer | Serve saved copies | Pick the best data center |
| Content | Original and live | Same for everyone, cached | Any request, passed through |
| Runs your code | Yes | No (mostly) | No |
| Good for | Login, create link, dashboards | Images, CSS, JS, public pages | Dynamic requests from users worldwide |
| Failure in one region | Needs another region | Another PoP serves the copy | Moves users to another region |
They work together in layers:
1User → CDN edge ← static files answered here2 │3 └→ Global LB → Data Center → Load Balancer → App Servers (dynamic requests)Use a CDN for anything the same for everyone. Use the global load balancer and your servers for anything personal or live.
Interview angle. Interviewers expect you to:
- Say what is cached (static and public files) and what is not (personal data).
- Explain how updates work (versioned file names, purge, TTL).
- Mention the hit ratio and why it matters.
Common mistakes:
- Saying "a CDN makes the whole system faster". It helps only for cacheable content.
- Forgetting about invalidation.
- Mixing up a CDN with a load balancer.
Summary
1CDN → servers around the world that keep copies of content near users2→ Needed because distance adds latency and the origin sends the same files again and again3→ Request flow: user → edge → hit (serve copy) or miss (fetch from origin, save)4→ Edge servers live in PoPs, sometimes behind a regional cache5→ Cache static and public content, never personal content6→ Hit ratio decides speed and origin load (95% hits = about 32 ms average)7→ Pull CDN fills itself on demand, push CDN is uploaded ahead of time8→ Cache-Control and TTL set how long a copy stays fresh9→ Update with versioned file names, purge, or a short TTL10→ Routing uses DNS or anycast to pick the nearest healthy PoP11→ Limits: stale content, cold misses, wrong caching, cost, less visibility12→ CDN serves copies, global load balancer picks data centers, origin creates answersOur files are now served from close to users, but the data behind ShortLink keeps growing and one database cannot hold or serve all of it. Splitting that data into smaller parts is partitioning, our next topic.