LogIn
I don't have account.

Content Delivery Network (CDN) in System Design: A Simple Guide with Real Examples

Neel Mishra
32 Views

#distributed-system

#distribution-strategy

#cloud-architecture

#content-delivery-network

If you want to understand CDN in system design, the morning of June 8, 2021 is a good place to start. That morning, a lot of the internet went dark at once. News sites, shopping sites, government pages and streaming services started showing error pages, all within the same minute. None of these companies had a problem with their own servers. They all used the same CDN, Fastly and Fastly was having a bad day.

Fastly's incident summary explains what happened. On May 12, a software release had quietly added a bug. Nearly a month later, one customer pushed a perfectly valid settings change that happened to trigger it and 85% of Fastly's network started returning errors. Fastly spotted the problem within a minute and had 95% of the network working normally within 49 minutes. But for those minutes, a single CDN was the front door for a big slice of the web and the door was stuck.

That story shows both sides of a content delivery network. A CDN makes websites fast and protects them from traffic floods, which is why so many large sites use one. It also becomes one of the most important parts of your system, so you need to understand how it works, how to set it up and what happens when it fails.

This guide explains CDNs in plain English, from the basics to production details: what a CDN is, why distance makes websites slow, how requests reach the nearest server, how caching rules work, how to purge content, how to keep private data out of the cache, how video streaming uses CDNs, real outages and security incidents, cost, monitoring and how to talk about CDNs in a system design interview. The code examples were all run and the outputs shown are real.

CDN in 60 seconds

  • What it is: a network of servers spread around the world that keep copies of your content close to users.
  • Why it helps: shorter distance means faster pages. Copies at the edge also mean far fewer requests reach your own servers.
  • How it works: a user's request goes to the nearest CDN server. If it has a fresh copy (a cache hit), it answers right away. If not (a cache miss), it fetches from your server, keeps a copy and answers.
  • What you control: mostly HTTP headers like Cache-Control, plus CDN settings for cache keys, purging and security.
  • Biggest risks: caching private data by mistake, serving stale content and the CDN itself becoming a single point of failure.

What Is a CDN?

A Content Delivery Network (CDN) is a group of servers placed in many locations around the world that store copies of a website's content and deliver it to users from the closest location. This cuts loading time, reduces load on the main server and helps absorb traffic spikes and attacks.

Think about how a big retail chain gets products to you. It doesn't ship every packet of biscuits from one giant warehouse in another state. It keeps stock in local stores near where people live. You walk to the nearby shop and it's usually there. If the shop runs out, it orders more from the warehouse.

A CDN works the same way:

  • The warehouse is your origin server, where the real content lives.
  • The local shops are edge servers, spread across many cities.
  • Stock on the shelf is cached content.
  • Running out and reordering is a cache miss.

Key CDN terms in plain English

Term What it means
Origin Your own server (or storage like Amazon S3) that holds the original content.
Edge server A CDN server close to users that keeps and serves copies.
PoP (Point of Presence) A CDN location, usually a data center with many edge servers.
Cache hit The edge already has a fresh copy and answers by itself.
Cache miss The edge doesn't have it (or it's too old), so it asks the origin.
TTL (Time to Live) How long a copy counts as fresh.
Purge (invalidation) Telling the CDN to throw away a copy before its TTL ends.
Cache key The "name" the CDN uses to look up a copy, usually based on the URL.
Hit ratio The share of requests answered from cache. Higher is better.
Origin offload How much traffic the CDN keeps away from your origin.

What a CDN can serve

CDNs started as a way to deliver static files: images, CSS, JavaScript, fonts, downloads and video. These are the same for every user, so one copy can serve millions of people.

Modern CDNs do much more. They can cache API responses, terminate HTTPS connections, block attacks, run small pieces of code at the edge, resize images on the fly and stream live video. But the core idea is still the same: do as much work as possible close to the user and bother the origin as little as possible.

Why Do We Need a CDN?

Distance makes the web slow

Data travels through fiber-optic cables at roughly two-thirds the speed of light, about 200,000 km per second. That sounds instant, but the world is big.

Mumbai to a data center in Virginia (a very common place to host servers) is about 12,850 km in a straight line. Even in a perfect world, a single round trip takes at least 128 milliseconds. Real cables don't follow straight lines, so actual numbers are higher.

And loading a page isn't one round trip. A brand new HTTPS connection needs one round trip for the TCP handshake, at least one more for TLS (the encryption setup) with TLS 1.3 and then one more for the actual request. That's three round trips or roughly 385 ms of pure travel time before the first byte of the page arrives and that's the best case.

Now put an edge server in Mumbai. A round trip to a server in the same city takes a few milliseconds. The same three round trips now cost almost nothing.


WITHOUT A CDN                                   WITH A CDN

User in Mumbai                                   User in Mumbai
     │                                                │
     │  ~12,850 km each way                           │  a few km
     │  ≥128 ms per round trip                        │  a few ms per round trip
     ▼                                                ▼
┌──────────────────┐                          ┌──────────────────┐
│ Origin server in │                          │ CDN edge in      │──── only on a miss ────┐
│ Virginia, USA    │                          │ Mumbai           │                        ▼
└──────────────────┘                          └──────────────────┘              ┌──────────────────┐
                                                                                │ Origin, Virginia │
                                                                                └──────────────────┘

Your origin can't handle everyone

Even if distance didn't matter, one origin can only serve so many requests. Say an e-commerce site launches a big sale. Every product page has 30 images. If a million people visit, that's 30 million image requests. If the CDN answers 95% of them from cache, the origin only sees 1.5 million. That's the difference between needing a huge fleet of servers and needing a modest one.

Bandwidth costs money

Cloud providers charge for data leaving their network ("egress"). A CDN that serves most bytes from its own edge means far fewer bytes leave your origin. CDN bandwidth isn't free either, but it's often cheaper per GB than origin egress at scale and it comes with the speed and protection benefits.

Traffic spikes and attacks

A CDN has far more total capacity than a typical company's servers. That's useful in two situations:

  • Good spikes: a product goes viral, a match result comes out, tickets go on sale.
  • Bad spikes: a DDoS attack (Distributed Denial of Service), where attackers flood you with fake traffic to knock you offline.

Because the CDN sits in front of your origin, it can absorb or filter a lot of that traffic before it ever reaches you.

Benefits at a glance

Benefit Why it happens
Faster page loads Content served from a nearby city
Less origin load Most requests answered from cache
Lower origin bandwidth bills Fewer bytes leave your origin
Better uptime Edges can keep serving cached content even if the origin struggles
DDoS protection Huge spare capacity in front of your servers
HTTPS at the edge Encryption handshakes finish close to the user

How Does a CDN Work? Step by Step

Here's what happens when a user in Pune opens https://shop.example.com/img/shoe-123.jpg and the site uses a CDN.


 ① User's browser asks DNS: "Where is shop.example.com?"
            │
            ▼
 ② DNS (or anycast routing) points the user to a nearby CDN PoP, say Mumbai
            │
            ▼
 ③ Browser connects to the Mumbai edge server (HTTPS handshake happens here)
            │
            ▼
 ④ Edge looks up its cache using the cache key (/img/shoe-123.jpg)
            │
     ┌──────┴───────────────────────────────┐
     │ HIT: fresh copy found                │ MISS: no copy or copy is too old
     ▼                                      ▼
 ⑤ Send it to the user              ⑤ Ask the origin (maybe via a regional "shield" cache)
    immediately                             │
                                            ▼
                                    ⑥ Origin replies with the image + caching headers
                                            │
                                            ▼
                                    ⑦ Edge stores a copy (if the headers allow it)
                                       and sends it to the user

The next user in Mumbai who asks for the same image gets a cache hit at step ④. That's the whole trick, repeated across hundreds of cities and billions of requests.

How users reach the nearest edge

There are two main ways a CDN sends users to a nearby server.

DNS-based routing. When the browser looks up the website's address, the CDN's DNS servers answer with the IP address of a good edge server for that user, based on location and current load. Akamai's research paper "The Akamai Network" (2010) describes a mapping system that works this way. One limitation: DNS sees the location of the user's DNS resolver, not always the user, so a user on a far-away public resolver can be sent to a less ideal edge. An extension called EDNS Client Subnet helps by passing part of the user's IP address along.

Anycast routing. Many edge locations announce the same IP address to the internet. The internet's routing system (BGP) naturally sends each user to the "closest" one in network terms. Cloudflare's documentation describes its network as using anycast. It's simple for users and great at spreading out DDoS traffic, but "closest by routing" isn't always "fastest," and you have less fine-grained control.

DNS-based Anycast
How it picks an edge DNS answer differs per user Same IP everywhere, routing picks
Control Fine-grained, can consider load Coarser, follows internet routing
Failover speed Limited by DNS caching (TTL) Fast, routes withdraw automatically
DDoS spreading Good Very good, attack traffic splits naturally

Many CDNs combine both.

Pull CDN vs push CDN

Pull CDN

The edge fetches content from your origin the first time someone asks for it. You don't upload anything to the CDN. This is the most common model because it's easy: point the CDN at your origin and set caching headers.

Push CDN

You upload content to the CDN's storage ahead of time. The CDN never needs to "go back" to fetch it. This fits large files that rarely change, like software downloads or video libraries, where you want everything in place before users arrive.

Pull CDN Push CDN
Setup Easy, just point at origin You upload and manage files
First request Slower (cache miss) Fast (already there)
Storage CDN keeps only what's requested You pay to store everything
Best for Websites, images, APIs Big downloads, video catalogs

Netflix's own CDN is a famous version of the push idea, covered later in this article.

How CDN Caching Works: Cache-Control and Friends

A CDN mostly decides what to cache and for how long, by reading HTTP headers your origin sends. The rules come from the HTTP caching standard, RFC 9111. If you learn one thing from this article, learn these headers.

The Cache-Control header

Directive Plain meaning
public Any cache, including a CDN, may store this.
private Only the user's own browser may store it. CDNs must not.
no-store Nobody stores it, anywhere.
no-cache Caches may store it, but must check with the origin before every reuse. (The name is confusing: it doesn't mean "don't cache.")
max-age=N Fresh for N seconds.
s-maxage=N Fresh for N seconds in shared caches like CDNs. Overrides max-age for them.
immutable This exact URL will never change, so don't even bother checking (RFC 8246).
stale-while-revalidate=N After it expires, serve the old copy for up to N seconds while fetching a new one in the background (RFC 5861).
stale-if-error=N If the origin is failing, serve the old copy for up to N seconds instead of an error (RFC 5861).

Support for some directives (especially the stale-* ones) varies between CDNs, so check your provider's docs. Most CDNs also let you override headers with their own rules.

Three common patterns

  1. Versioned static files (app.3f9a1c.js, logo.v7.png): cache for a year with public, max-age=31536000, immutable. When the file changes, your build tool gives it a new name, so the old copy simply stops being requested. This trick is called cache busting or fingerprinting and it's the cleanest way to avoid stale files.
  2. HTML pages and things that change without changing their URL: use a short TTL (s-maxage=60) or no-cache with an ETag, so the CDN revalidates cheaply.
  3. Personal data (account pages, carts, anything after login): private, no-store. Never in a shared cache.

Revalidation with ETag (cheap freshness checks)

An ETag is a short label for a specific version of a file, like a fingerprint. When a cached copy needs checking, the CDN sends the ETag back to the origin in an If-None-Match header. If nothing has changed, the origin replies 304 Not Modified with no body. That saves bandwidth and the CDN keeps using its copy.

The small Java program below acts as an origin with all three patterns, plus a client that requests each one:


import com.sun.net.httpserver.HttpServer;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.http.*;
import java.nio.charset.StandardCharsets;

// A tiny origin server that sends the cache headers a CDN reads, plus a client that shows the results.
public class OriginServer {
    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);

        // 1. Fingerprinted static file: safe to cache for a year, the name changes when the content does.
        server.createContext("/static/app.3f9a1c.js", ex -> {
            byte[] body = "console.log('hello');".getBytes(StandardCharsets.UTF_8);
            ex.getResponseHeaders().set("Cache-Control", "public, max-age=31536000, immutable");
            ex.sendResponseHeaders(200, body.length);
            ex.getResponseBody().write(body);
            ex.close();
        });

        // 2. HTML page: CDN may store it, but must check with the origin before reusing it.
        String html = "<h1>Home</h1>";
        String etag = "\"v42\"";
        server.createContext("/index.html", ex -> {
            ex.getResponseHeaders().set("Cache-Control", "no-cache");
            ex.getResponseHeaders().set("ETag", etag);
            String ifNoneMatch = ex.getRequestHeaders().getFirst("If-None-Match");
            if (etag.equals(ifNoneMatch)) {
                ex.sendResponseHeaders(304, -1);          // "Not Modified": no body sent
            } else {
                byte[] body = html.getBytes(StandardCharsets.UTF_8);
                ex.sendResponseHeaders(200, body.length);
                ex.getResponseBody().write(body);
            }
            ex.close();
        });

        // 3. Personal page: never store it in any shared cache.
        server.createContext("/account", ex -> {
            byte[] body = "{\"name\":\"Asha\",\"wallet\":1200}".getBytes(StandardCharsets.UTF_8);
            ex.getResponseHeaders().set("Cache-Control", "private, no-store");
            ex.sendResponseHeaders(200, body.length);
            ex.getResponseBody().write(body);
            ex.close();
        });

        server.start();

        HttpClient client = HttpClient.newHttpClient();
        for (String path : new String[]{"/static/app.3f9a1c.js", "/index.html", "/account"}) {
            HttpResponse<String> r = client.send(
                    HttpRequest.newBuilder(URI.create("http://localhost:8080" + path)).build(),
                    HttpResponse.BodyHandlers.ofString());
            System.out.printf("%-24s %d  Cache-Control: %s%n", path, r.statusCode(),
                    r.headers().firstValue("cache-control").orElse("-"));
        }

        // Revalidation: the CDN (or browser) sends back the ETag it already has.
        HttpResponse<String> again = client.send(
                HttpRequest.newBuilder(URI.create("http://localhost:8080/index.html"))
                        .header("If-None-Match", "\"v42\"").build(),
                HttpResponse.BodyHandlers.ofString());
        System.out.printf("%-24s %d  body bytes: %d%n", "/index.html (revalidate)",
                again.statusCode(), again.body().length());

        server.stop(0);
    }
}

Run it with java OriginServer.java. Output:

/static/app.3f9a1c.js    200  Cache-Control: public, max-age=31536000, immutable
/index.html              200  Cache-Control: no-cache
/account                 200  Cache-Control: private, no-store
/index.html (revalidate) 304  body bytes: 0

The last line is the point of ETags: the check costs a tiny response with zero body bytes instead of the full page.

The Vary header

Sometimes one URL has more than one correct answer. A server might send a compressed version to browsers that support it and an uncompressed one to others. The Vary header tells caches which request headers change the response, for example Vary: Accept-Encoding. The CDN then keeps separate copies per value.

Be careful with it. Vary: User-Agent can split one file into thousands of copies (one per browser version) and your hit ratio collapses. Many CDNs normalize common cases like Accept-Encoding for you, but varying on high-variety headers is a classic way to quietly ruin caching.

Choosing a TTL

There's no perfect TTL. It's a trade-off between freshness and hit ratio:

Content Typical approach Why
Versioned JS, CSS, images 1 year + immutable URL changes when content changes
Product images without versions Hours to days, plus purge on update Rarely change; purge handles exceptions
Home page, category pages Seconds to minutes, plus stale-while-revalidate Change often, but brief staleness is OK
Prices, stock, cart, checkout Don't cache or cache for very short with care Wrong values cost money or trust
Logged-in pages private, no-store Personal data

A useful rule: the more often content changes and the more it matters if it's wrong, the shorter the TTL. And if you can version the URL, do that instead of fighting TTLs.

Cache Keys and Hit Ratio: Where Performance Is Won or Lost

The cache key is how a CDN decides whether two requests are asking for "the same thing." By default, it's usually the host plus the full URL, including the query string.

That default causes one of the most common CDN problems. These URLs return the exact same image:


/img/product-42.jpg
/img/product-42.jpg?utm_source=mail&utm_id=88123
/img/product-42.jpg?utm_source=mail&utm_id=90417

But with the default key, the CDN treats them as three different files, so each one is a separate cache miss. Marketing tracking parameters like utm_* are unique per campaign or per click, so they can turn your best-cached content into a stream of misses.

To show how much this matters, here's a simulation of an edge cache. It uses an LRU cache (least recently used items get evicted first) and "Zipf" traffic, a common model where a few items are very popular and most items are rarely requested, which is how real product catalogs and videos tend to behave.


import java.util.*;

// Toy edge cache: LRU, popular-content-heavy (Zipf) traffic.
// Shows (1) hit ratio vs cache size and (2) what tracking parameters do to the cache key.
public class EdgeCacheSim {

    static final class LruCache extends LinkedHashMap<String, Boolean> {
        private final int capacity;
        LruCache(int capacity) { super(16, 0.75f, true); this.capacity = capacity; }
        @Override protected boolean removeEldestEntry(Map.Entry<String, Boolean> e) { return size() > capacity; }
    }

    // Zipf sampler: item k (1-based) is requested with probability proportional to 1/k^s.
    static int[] zipfSample(int items, double s, int count, Random rnd) {
        double[] cdf = new double[items];
        double sum = 0;
        for (int k = 1; k <= items; k++) { sum += 1.0 / Math.pow(k, s); cdf[k - 1] = sum; }
        int[] out = new int[count];
        for (int i = 0; i < count; i++) {
            double u = rnd.nextDouble() * sum;
            int idx = Arrays.binarySearch(cdf, u);
            out[i] = idx >= 0 ? idx : -idx - 1;
        }
        return out;
    }

    // Normalize a cache key: drop utm_* tracking params, sort the rest.
    static String normalize(String url) {
        int q = url.indexOf('?');
        if (q < 0) return url;
        List<String> kept = new ArrayList<>();
        for (String p : url.substring(q + 1).split("&")) {
            if (!p.startsWith("utm_")) kept.add(p);
        }
        Collections.sort(kept);
        return kept.isEmpty() ? url.substring(0, q) : url.substring(0, q) + "?" + String.join("&", kept);
    }

    static double run(String[] urls, int capacity, boolean normalizeKeys) {
        LruCache cache = new LruCache(capacity);
        long hits = 0;
        for (String u : urls) {
            String key = normalizeKeys ? normalize(u) : u;
            if (cache.get(key) != null) hits++; else cache.put(key, Boolean.TRUE);
        }
        return 100.0 * hits / urls.length;
    }

    public static void main(String[] args) {
        int catalog = 100_000, requests = 1_000_000;
        Random rnd = new Random(7);
        int[] ids = zipfSample(catalog, 1.0, requests, rnd);

        String[] clean = new String[requests];
        String[] tracked = new String[requests];
        for (int i = 0; i < requests; i++) {
            clean[i] = "/img/product-" + ids[i] + ".jpg";
            // 30% of visits arrive from campaigns with a unique tracking value
            tracked[i] = rnd.nextDouble() < 0.30
                    ? clean[i] + "?utm_source=mail&utm_id=" + rnd.nextInt(1_000_000)
                    : clean[i];
        }

        System.out.println("Catalog: 100,000 images, 1,000,000 requests, Zipf(s=1.0)");
        for (int cap : new int[]{1_000, 5_000, 20_000}) {
            System.out.printf("cache holds %,6d objects -> hit ratio %5.1f%%%n", cap, run(clean, cap, false));
        }
        System.out.println();
        System.out.printf("20,000-object cache, 30%% of URLs carry utm params, raw key:        %5.1f%%%n", run(tracked, 20_000, false));
        System.out.printf("20,000-object cache, 30%% of URLs carry utm params, normalized key: %5.1f%%%n", run(tracked, 20_000, true));
        System.out.println();
        System.out.println(normalize("/img/p-1.jpg?w=400&utm_source=mail&fmt=webp"));
    }
}

Output:

Catalog: 100,000 images, 1,000,000 requests, Zipf(s=1.0)
cache holds  1,000 objects -> hit ratio  50.6%
cache holds  5,000 objects -> hit ratio  66.5%
cache holds 20,000 objects -> hit ratio  80.7%

20,000-object cache, 30% of URLs carry utm params, raw key:         50.7%
20,000-object cache, 30% of URLs carry utm params, normalized key:  80.7%

/img/p-1.jpg?fmt=webp&w=400

Three things stand out:

  • A small cache does a lot of work. Holding just 1% of the catalog (1,000 of 100,000 images) answered about half of all requests. Holding 20% answered about 81%. That's the "popular stuff is very popular" effect and it's why CDNs work so well.
  • Tracking parameters hurt more than you'd guess. Only 30% of requests had them, yet the hit ratio fell from 80.7% to 50.7%, a drop of 30 points. The junk keys don't just miss; they also fill the cache and push out useful items.
  • Normalizing the key fixes it completely in this model. Dropping utm_* parameters and sorting the rest makes all versions share one cache entry.

This is a toy model with made-up traffic, so don't treat the exact percentages as real-world numbers. The shape of the result is what's useful. Most CDNs let you configure the cache key: which query parameters to include, ignore or sort and which headers or cookies to include. Review this early, because it's often the single biggest lever for hit ratio.

Cache Invalidation: How to Update Content on a CDN

You updated a product photo, but users still see the old one. Now what? You have three main tools.

1. Wait for the TTL to expire

The simplest option and fine when the TTL is short. Not great when the TTL is a day and the old image is wrong.

2. Purge (invalidate)

Tell the CDN to throw away specific copies right now. Every major CDN has an API for this. Some examples:


# Amazon CloudFront: invalidate one path (or use "/*" for everything)
aws cloudfront create-invalidation --distribution-id E1234567890ABC --paths "/img/product-42.jpg"

# Cloudflare: purge specific URLs
curl -X POST "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/purge_cache" \
     -H "Authorization: Bearer <API_TOKEN>" -H "Content-Type: application/json" \
     --data '{"files":["https://shop.example.com/img/product-42.jpg"]}'

# Fastly: purge everything tagged with a surrogate key
curl -X POST "https://api.fastly.com/service/<SERVICE_ID>/purge/product-42" \
     -H "Fastly-Key: <API_TOKEN>"

Purges aren't free in every sense. Some providers charge for large numbers of invalidations (CloudFront, for example, charges for invalidation paths beyond a monthly free allowance; check current pricing). And purging everything at once (/*) sends a wave of misses to your origin, which can overload it.

3. Purge by tag (surrogate keys)

What if one product change affects many URLs: the product page, three image sizes, the category page and the search results page? Purging each URL by hand is error-prone.

Tag-based purging fixes that. Your origin adds a header listing tags for each response, for example Surrogate-Key: product-42 category-shoes on Fastly or a Cache-Tag header on Cloudflare. When product 42 changes, you purge the tag product-42 and every cached response with that tag is removed together.

4. Version the URL (the best option when you can)

Instead of changing content behind the same URL, give the new content a new URL: shoe-42.v8.jpg instead of shoe-42.jpg. The new page points at the new URL. Nothing to purge, no stale copies and the old file can be cached forever because nobody asks for it anymore.

Method Speed Effort Best for
Wait for TTL Slow None Short-TTL content
Purge by URL Fast Medium A few known URLs
Purge by tag Fast Setup once, then easy Content that appears on many pages
Versioned URLs Instant Build tooling JS, CSS, images, any static asset

Protecting the Origin: Shields, Tiered Caching and Request Collapsing

A CDN with hundreds of PoPs has a hidden problem. If each PoP misses separately, a newly published file might be fetched from your origin hundreds of times, once per location.

Origin shield and tiered caching

The fix is a middle layer. Edges first ask a regional or "shield" cache and only the shield talks to your origin.


 Users ──► Edge (Mumbai) ──┐
 Users ──► Edge (Delhi)  ──┼──► Shield cache (one region) ──► Origin
 Users ──► Edge (Chennai)──┘         (one fetch instead of three)

Different CDNs name this differently: CloudFront has Origin Shield, Fastly calls it shielding and Cloudflare offers Tiered Cache. The idea is the same.

Request collapsing (stopping the thundering herd)

Imagine a live cricket score file with a 5-second TTL. The moment it expires, thousands of users ask for it at the same time. If every one of those misses goes to the origin, that's a thundering herd and it can knock your origin over exactly when traffic is highest.

Request collapsing (Fastly's name for it; other CDNs have similar features) means the edge sends one request to the origin and makes everyone else wait for that same response. The program below shows the idea with 200 simultaneous requests:


import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

// 200 users ask the edge for the same object at the same moment, right after it expired.
public class Coalescing {
    static final AtomicInteger originCalls = new AtomicInteger();

    static String fetchFromOrigin(String key) {
        originCalls.incrementAndGet();
        try { Thread.sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
        return "content of " + key;
    }

    // Without coalescing: every miss goes to the origin.
    static String getNaive(String key) { return fetchFromOrigin(key); }

    // With coalescing: the first miss starts one fetch, everyone else waits for that same result.
    static final ConcurrentHashMap<String, CompletableFuture<String>> inFlight = new ConcurrentHashMap<>();
    static String getCoalesced(String key) {
        CompletableFuture<String> mine = new CompletableFuture<>();
        CompletableFuture<String> existing = inFlight.putIfAbsent(key, mine);
        if (existing != null) return existing.join();          // someone is already fetching
        try {
            String value = fetchFromOrigin(key);
            mine.complete(value);
            return value;
        } catch (RuntimeException e) {
            mine.completeExceptionally(e);
            throw e;
        } finally {
            inFlight.remove(key, mine);
        }
    }

    static int run(boolean coalesce) throws Exception {
        originCalls.set(0);
        ExecutorService pool = Executors.newFixedThreadPool(200);
        CountDownLatch start = new CountDownLatch(1);
        for (int i = 0; i < 200; i++) {
            pool.submit(() -> {
                start.await();
                return coalesce ? getCoalesced("/live/score.json") : getNaive("/live/score.json");
            });
        }
        start.countDown();
        pool.shutdown();
        pool.awaitTermination(10, TimeUnit.SECONDS);
        return originCalls.get();
    }

    public static void main(String[] args) throws Exception {
        System.out.println("origin calls without coalescing: " + run(false));
        System.out.println("origin calls with coalescing:    " + run(true));
    }
}

Output (the same on repeated runs):


origin calls without coalescing: 200
origin calls with coalescing:    1

Two hundred origin calls became one. In real life, a request that arrives just after the shared fetch finishes may start a new one, so the number won't always be exactly 1, but the herd is gone.

stale-while-revalidate attacks the same problem from another angle: users keep getting the slightly old copy instantly while one background request refreshes it.

Can a CDN Cache Dynamic Content and APIs?

Yes, more than most people expect, but carefully. Dynamic content is anything generated per request: search results, API responses, personalized pages. The question isn't "is it dynamic?" but "is the response the same for many users, at least for a few seconds?"

Content Cacheable at the CDN? How
Product details API (/api/products/42) Yes Short TTL + purge by tag on update
Search results for popular queries Often Very short TTL; include the query in the cache key
Exchange rates, sports scores Yes TTL of a few seconds + request collapsing
Home page for logged-out users Yes Short TTL or stale-while-revalidate
Cart, orders, account, wallet No private, no-store
Anything that depends on a cookie Only if the cookie is in the cache key, which usually kills the hit ratio Better to split the page (see below)

Even a TTL of one second can matter. If a popular API endpoint gets 5,000 requests per second, a one-second TTL turns that into roughly one origin request per second per edge (or per shield, with tiered caching).

Splitting pages: cache the shell, fetch the personal bits

A common pattern for personalized pages: cache the main page (the same for everyone) and load the personal parts (name, cart count, recommendations) with a separate uncached API call from the browser. The heavy part is served from the edge; only the small personal part hits the origin.

Edge computing

Most large CDNs now let you run code at the edge: Cloudflare Workers, AWS Lambda@Edge and CloudFront Functions, Fastly Compute and Akamai EdgeWorkers are examples. Typical uses:

  • Redirects and URL rewrites
  • A/B test assignment
  • Checking authentication tokens before serving content
  • Normalizing cache keys
  • Adding security headers

Edge code is powerful, but it's harder to test and debug than code on your own servers and a bug there affects every request. Keep it small.

How CDNs Power Video Streaming

Video is where CDNs matter most, because video files are huge and everyone wants them to start instantly.

Modern streaming uses formats like HLS and MPEG-DASH. A video is cut into small chunks (a few seconds each) at several quality levels. The player downloads chunks one by one and switches quality based on the user's connection. This is called adaptive bitrate streaming. Each chunk is a normal HTTP file, which makes it perfect for CDN caching: the first viewer in a city pulls a chunk to the edge and everyone after that gets it from nearby.

Live streaming works the same way, but chunks are created in real time and have very short lifetimes, so request collapsing and shielding become critical when a whole country tunes in at the same moment.

Netflix Open Connect: a CDN built for one company

Netflix runs its own CDN, called Open Connect and documents it publicly. According to Netflix's Open Connect overview and its company announcement:

  • Netflix started Open Connect in 2011 because of the growing scale of its streaming.
  • It builds its own servers, called Open Connect Appliances (OCAs) and provides them free of charge to qualifying internet service providers (ISPs), who host them inside their own networks. The ISP provides power, space and connectivity.
  • Content is copied to these appliances ahead of time, during off-peak hours ("fill windows"), instead of being pulled when someone presses play.
  • With appliances installed inside an ISP, almost all Netflix viewing for that ISP's customers is served locally, instead of crossing the wider internet.

This is the push model at enormous scale. It works because Netflix's catalog is known in advance and popularity is fairly predictable, so it can place the right files in the right cities before anyone asks. Most companies don't have that kind of scale or predictability, which is why they use commercial CDNs instead of building their own.

CDN Security: Benefits and Real Risks

A CDN sits between every user and your servers, so it's both a strong security layer and a place where mistakes get amplified.

Security features a CDN gives you

  • DDoS absorption: a huge network soaks up floods of traffic that would knock over a single data center.
  • Web Application Firewall (WAF): rules that block common attacks, like SQL injection, before they reach your app.
  • TLS at the edge: HTTPS handled close to users, with managed certificates.
  • Bot management and rate limiting: slow down scrapers and credential-stuffing attacks.
  • Origin hiding: users only see the CDN's addresses, not your origin's.

Origin hiding only works if you lock the origin down. If your origin accepts traffic from anyone, attackers can find its address and go around the CDN entirely. Allow only the CDN's IP ranges or require a secret header or mutual TLS between the CDN and origin. For S3 behind CloudFront, AWS provides origin access controls so the bucket isn't public.

Signed URLs: sharing content with only some people

What if you sell an online course and want only paying users to watch the videos, while still serving them from the CDN? The usual answer is a signed URL: a link with an expiry time and a cryptographic signature. The edge checks the signature before serving. Anyone who changes the file name or the expiry breaks the signature.

Every CDN has its own format (CloudFront uses signed URLs and signed cookies based on key pairs, for example). The Java program below shows the general idea with an HMAC signature:


import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;

// Generic HMAC token for expiring links. The origin signs; the edge checks before serving.
public class SignedUrl {
    private static final byte[] SECRET = "replace-with-a-long-random-secret".getBytes(StandardCharsets.UTF_8);

    static String sign(String path, long expiresAtEpochSec) throws Exception {
        String token = hmac(path + "|" + expiresAtEpochSec);
        return path + "?expires=" + expiresAtEpochSec + "&token=" + token;
    }

    static boolean verify(String path, long expires, String token, long nowEpochSec) throws Exception {
        if (nowEpochSec > expires) return false;                       // link has expired
        byte[] expected = hmac(path + "|" + expires).getBytes(StandardCharsets.UTF_8);
        return MessageDigest.isEqual(expected, token.getBytes(StandardCharsets.UTF_8)); // constant-time compare
    }

    private static String hmac(String data) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(SECRET, "HmacSHA256"));
        return Base64.getUrlEncoder().withoutPadding()
                .encodeToString(mac.doFinal(data.getBytes(StandardCharsets.UTF_8)));
    }

    public static void main(String[] args) throws Exception {
        long now = 1_800_000_000L;                 // fixed "current time" so the output is repeatable
        String path = "/videos/course-12/lesson-3.mp4";
        String url = sign(path, now + 600);        // valid for 10 minutes
        System.out.println(url);

        String token = url.substring(url.indexOf("token=") + 6);
        System.out.println("valid link:          " + verify(path, now + 600, token, now));
        System.out.println("after it expires:    " + verify(path, now + 600, token, now + 601));
        System.out.println("expiry changed:      " + verify(path, now + 86_400, token, now));
        System.out.println("different file:      " + verify("/videos/course-12/lesson-4.mp4", now + 600, token, now));
    }
}

Output:


/videos/course-12/lesson-3.mp4?expires=1800000600&token=f1mZgzdMcPg7oTDzxtPcmLKzlJWxGO3_ngKbG6en9E8
valid link:          true
after it expires:    false
expiry changed:      false
different file:      false

Two details matter. The comparison uses MessageDigest.isEqual, which takes the same time whether the first or last character is wrong, so attackers can't guess the token piece by piece from timing. And the secret must be long, random and kept out of source code in real systems; the one above is a placeholder.

One more thing: make sure the cache key ignores token and expires or every signed link becomes its own cache entry and you're back to the hit-ratio problem from earlier. Most CDNs that support token auth handle this for you.

Real incident: Steam's Christmas caching mistake (2015)

On December 25, 2015, Steam (Valve's gaming store) was hit by a denial-of-service attack. To cope, its caching partner deployed new caching rules. According to Valve's statement, the second set of rules incorrectly cached pages for logged-in users. Between 11:50 and 13:20 Pacific time, store pages generated for about 34,000 users, some containing personal information, may have been shown to other users. Valve shut the store down and deployed a corrected configuration.

The mistake is easy to make under pressure: a rule meant for public pages also matched pages that depended on who was logged in. The defenses are boring but effective:

  • Mark every personalized response private, no-store at the origin, so even a bad CDN rule has a clear signal not to cache it.
  • Make the CDN bypass the cache when a session cookie or Authorization header is present, unless you've deliberately designed for it.
  • Treat CDN configuration changes like code: review them, test them and roll them out gradually, especially during incidents, when people are rushed.

Web cache poisoning and web cache deception

Two attack classes are worth knowing by name, because they target the gap between what the cache thinks and what the origin does.

  • Web cache poisoning: the attacker sends a request with a header the cache ignores but the origin uses (for example, a forwarded-host header that changes links in the page). The origin builds a harmful response, the cache stores it under the normal URL and then serves it to everyone. James Kettle's 2018 PortSwigger research, "Practical Web Cache Poisoning," showed this against real sites. Defense: anything that changes the response must be in the cache key and the origin should ignore headers it doesn't need.
  • Web cache deception: the attacker tricks a victim into visiting something like /account/profile.css. The origin ignores the fake .css ending and returns the victim's account page; the CDN sees .css, assumes it's a static file and caches it publicly. The attacker then requests the same URL and reads the victim's data. Omer Gil presented this at Black Hat USA in 2017. Defense: cache based on the origin's Cache-Control headers rather than file extensions and make the origin return errors for paths that don't exist instead of a "close enough" page.

Real incident: Cloudbleed (2017)

In February 2017, Tavis Ormandy of Google Project Zero reported that Cloudflare's edge was leaking pieces of memory into some HTTP responses, because of a bug in an HTML parser. Those responses could contain data from other customers' traffic and some had been stored by search engine caches before they were cleaned up. Cloudflare published a detailed incident report and worked with search engines to purge the cached data. It's a reminder that a CDN processes your users' traffic in plaintext at the edge, so its software quality is part of your security.

When the CDN Fails: Real Outages and How to Prepare

A CDN makes your system more reliable most of the time. But because so much traffic flows through it, a CDN failure is a big failure. Three well-documented outages show different ways it can go wrong.

1. Fastly, June 8, 2021: a valid config triggers a hidden bug

As described at the start, a bug shipped on May 12 waited until a customer's valid configuration change triggered it on June 8. 85% of Fastly's network returned errors and 95% was back within 49 minutes (Fastly). Fastly's own summary says it should have anticipated the failure, even though the trigger conditions were very specific.

2. Cloudflare, July 2, 2019: one regular expression

Cloudflare deployed a new WAF rule containing a regular expression that backtracked badly: on certain inputs, the regex engine tried an enormous number of possibilities. That pushed CPUs to 100% on the machines handling HTTP traffic worldwide and most Cloudflare traffic was disrupted for 27 minutes. Cloudflare's detailed write-up explains that the real story was a chain of process issues, not just one bad regex and describes follow-up changes, including moving to a regex engine that guarantees bounded run time.

3. Cloudflare, November 18, 2025: a generated file grows too big

A permissions change on a database cluster caused a query to return duplicate rows. That query built a "feature file" used by Cloudflare's bot management system, so the file doubled in size. The file was automatically pushed across the network and it exceeded a size limit in the core proxy software, which then failed. According to Cloudflare's post-mortem, core traffic began failing at 11:20 UTC, was largely restored by 14:30 UTC and everything was back to normal by 17:06 UTC. Cloudflare called it its worst outage since 2019.

The pattern behind all three

These outages had different causes, but they share a shape:

  1. A change that looked safe (a valid config, a routine rule, a permissions tweak).
  2. Spread very fast across the whole network, because fast global rollout is normally a feature.
  3. Hit a hidden limit or bug that only showed up at full scale.

So the defenses are also similar, both for CDN providers and for you as a customer:

  • Roll out config changes gradually, to a few locations first and watch error rates before going wider. Treat generated files and rules like code.
  • Validate inputs to critical systems, including files your own pipelines generate, with size and sanity checks.
  • Know your fallback. If the CDN fails, can you switch DNS to another CDN or straight to your origin? Can your origin survive the full, uncached traffic? If not, a bypass plan just moves the outage.
  • Consider multi-CDN for critical services: two providers, with DNS or traffic steering between them. It improves resilience, but you now maintain two sets of configuration, two sets of security rules and you lose some cache efficiency because each CDN warms its own cache. It's worth it for some businesses and overkill for many.
  • Keep your status page and incident tools off the CDN you're monitoring. If they depend on it, they go down with it.

Monitoring a CDN: What to Measure

A CDN can hide problems as well as solve them. These are the numbers worth watching:

Metric What it tells you Watch out for
Cache hit ratio (requests) Share of requests served from cache Sudden drops often mean a cache key or header change
Byte hit ratio Share of bytes served from cache Can differ a lot from request hit ratio; big files matter for cost
Origin offload / origin request rate How much traffic still reaches your servers Spikes after deploys or purges
Edge error rate (4xx/5xx) Errors users actually see Separate CDN-generated errors from origin errors
Time to first byte (TTFB) How fast the first byte arrives Compare per region; slow regions may need different routing
Origin latency from the CDN How long misses take Slow origin makes every miss slow
Purge time How long until a purge takes effect Matters for urgent fixes

Read the debug headers. Most CDNs add response headers that tell you what happened. Cloudflare sends CF-Cache-Status (values like HIT, MISS, EXPIRED, BYPASS, DYNAMIC). CloudFront sends X-Cache (for example, Hit from cloudfront or Miss from cloudfront). The standard Age header shows how many seconds a cached copy has been sitting in the cache. A quick curl -I https://your-site/path is often the fastest way to debug a caching issue.

Use both synthetic checks and real-user monitoring. Synthetic checks (scripted requests from many locations) catch outages quickly. Real-user monitoring (RUM), measured in actual browsers, shows what real people experience on real networks. You need both, because a CDN can look healthy from data centers and slow from mobile networks.

Alert on hit ratio, not just errors. A misconfigured cache key doesn't throw errors. It just quietly multiplies your origin load and bill.

CDN Cost: What You Pay For

CDN pricing differs by provider and contract, so check current pricing pages. The common pieces are:

  • Data transfer out (per GB delivered to users), often cheaper per GB at higher volumes and different by region.
  • Requests (per 10,000 or per million requests) on some providers.
  • Features: WAF, bot management, image optimization, edge compute, logs and dedicated support are often extra.
  • Invalidations on some providers, beyond a free allowance.
  • Origin egress: your cloud provider still charges for data the CDN pulls from your origin on misses.

The biggest cost lever is usually hit ratio. Every percentage point of misses is traffic you pay for twice: once at the origin and once at the CDN. Versioned URLs, clean cache keys, sensible TTLs and tiered caching save real money.

Popular CDN Providers Compared

This comparison sticks to well-documented features. Every provider below is a solid choice for most websites; the differences matter at the edges.

Provider Notable for Edge compute Good fit when
Cloudflare Anycast network; CDN bundled with DNS, WAF and DDoS protection Workers You want security and CDN in one place, with an easy setup
Akamai One of the oldest and most widely distributed CDNs; strong enterprise and media features EdgeWorkers Large enterprises, media and regulated industries
Amazon CloudFront Tight integration with AWS (S3, ALB, Shield, WAF) CloudFront Functions, Lambda@Edge Your stack already runs on AWS
Fastly Fine-grained control (VCL configuration), fast purging, surrogate keys Fastly Compute You need precise cache control and frequent purges
Google Cloud CDN Integrated with Google Cloud load balancing Through other Google Cloud services Your stack runs on Google Cloud
Azure Front Door Integrated with Azure, combines CDN with global load balancing Rules engine Your stack runs on Azure

The honest advice: pick the CDN that fits your existing cloud and team skills first, then check specific needs (purge speed, video, edge compute, regional coverage where your users are, pricing at your traffic level). Test performance from your real users' regions before committing, because coverage differs by country.

When to Use a CDN and When You Might Not Need One

Use a CDN when:

  • Your users are spread across cities or countries.
  • You serve images, video, downloads or JavaScript/CSS bundles.
  • You expect traffic spikes (sales, launches, live events).
  • You want DDoS protection and a WAF in front of your app.
  • Origin bandwidth costs are significant.

You might not need one (yet) when:

  • Your app is an internal tool used from one office or one region near your servers.
  • Almost every response is personal and uncacheable and your users are close to your servers. (Even then, a CDN can still help with TLS termination and attack protection.)
  • You're building a small prototype where simplicity matters more than speed.

Be careful when:

  • You're adding a CDN to a logged-in app for the first time. Audit every response's Cache-Control before turning caching on.
  • You have strict data residency rules. Check where the CDN stores and processes data.

How to Use a CDN in a System Design Interview

In most system design interviews, the CDN shows up in the first diagram: users → CDN → load balancer → app servers → database. The interviewer wants to see that you know what goes through it and why, not just that you drew the box.

A good way to talk about it:

  1. Say what it caches. "Static assets and images go through the CDN with long TTLs and versioned URLs. Product pages for logged-out users get a short TTL. Cart and checkout bypass the cache."
  2. Say how freshness works. "When a seller updates a product, we purge by a surrogate key for that product."
  3. Say how it protects the origin. "Origin shield and request collapsing keep misses from stampeding the origin. The origin only accepts traffic from the CDN."
  4. Say what happens if it fails. "If the CDN has an outage, we can fail over DNS to a second CDN; our origin is sized for that or we accept degraded performance."
  5. Mention a number when it helps. "With a 95% hit ratio, the origin handles 5% of image traffic."

Example: designing image delivery for an e-commerce app

  • Sellers upload images to object storage (like S3). An image service creates sizes like 200px, 800px and 1600px and versioned file names like p42-800.v3.webp.
  • The CDN serves images with public, max-age=31536000, immutable. Updating an image means a new version number, so no purge is needed.
  • The cache key ignores tracking parameters and keeps only width and format.
  • An origin shield sits in front of storage. Storage is private and only accessible from the CDN.
  • Product pages for logged-out users are cached for 60 seconds with stale-while-revalidate; prices and stock are fetched by a separate, uncached API call.
  • Monitoring tracks hit ratio, byte hit ratio, origin request rate and edge 5xx errors per region.

Common CDN Mistakes

1. Caching personalized pages. The Steam incident in one line. Always mark personal responses private, no-store and bypass the cache when session cookies are present.

2. Letting junk into the cache key. Tracking parameters, random query strings or Vary: User-Agent can cut your hit ratio dramatically, as the simulation showed.

3. Long TTLs on unversioned URLs. If app.js is cached for a year and you change it, users get the old one. Version your static files.

4. Purging everything after every deploy. A full purge sends all traffic to the origin at once. Purge narrowly, by tag or use versioned URLs.

5. Leaving the origin open to the internet. Attackers can skip the CDN and its protections. Restrict the origin to CDN traffic.

6. Relying on file extensions to decide what's cacheable. That's the opening for web cache deception. Trust the origin's headers instead.

7. Forgetting that misses can be slow. If the origin is slow, every miss is slow. A CDN hides a slow origin only for popular content.

8. No plan for CDN failure. Know whether you can bypass or switch providers and whether your origin can take the load.

9. Not monitoring hit ratio. A broken cache key causes no errors, only higher latency and bills.

10. Treating CDN config changes as "just settings." Many of the worst CDN incidents started with configuration. Review, test and roll out changes gradually.

CDN Interview Questions (with Answers)

Beginner

Q1. What is a CDN and why do we use it?

A CDN is a network of servers in many locations that store copies of content close to users. It reduces latency because data travels a shorter distance, reduces load and bandwidth costs on the origin because most requests are answered from cache and helps absorb traffic spikes and DDoS attacks.

Q2. What is a cache hit and a cache miss?

A hit means the edge server already had a fresh copy and answered by itself. A miss means it didn't, so it fetched the content from the origin (or a shield cache), stored it if allowed and then answered.

Q3. What kind of content is best for a CDN?

Content that's the same for many users: images, video, CSS, JavaScript, fonts, downloads and public pages. Personalized content like carts and account pages should not be cached in a shared cache.

Q4. What is TTL in a CDN?

Time to live: how long a cached copy counts as fresh before the CDN must fetch or revalidate it. It's usually set with Cache-Control: max-age or s-maxage.

Intermediate

Q5. How do you update a file that's already cached on the CDN?

Wait for the TTL, purge it by URL, purge by tag (surrogate key) if it appears on many pages or best of all, publish it under a new versioned URL so there's nothing to purge.

Q6. What's the difference between no-cache and no-store?

no-cache lets caches store the response but requires them to check with the origin before every reuse, usually via an ETag and a cheap 304 response. no-store forbids storing it at all.

Q7. How does a CDN route a user to the nearest server?

Either with DNS (the CDN's DNS returns a nearby edge's IP based on the resolver's location and server load) or with anycast (many locations share one IP and internet routing sends the user to the nearest one). Many CDNs use both.

Q8. What is an origin shield?

A middle cache layer between edges and the origin. Edge misses go to the shield first, so the origin receives one request for new content instead of one per edge location.

Advanced

Q9. What is the thundering herd problem and how does a CDN handle it?

When a popular item expires, many simultaneous requests miss together and all hit the origin. CDNs handle it with request collapsing (one origin fetch, everyone waits for it), stale-while-revalidate (serve the old copy while one request refreshes it) and shielding.

Q10. What is web cache poisoning and how do you prevent it?

An attacker gets the cache to store a harmful response, usually by sending a header that changes the origin's response but isn't part of the cache key. Prevent it by including every response-changing input in the cache key, stripping or ignoring unneeded headers at the origin and not reflecting request headers into cached responses.

Q11. How would you cache an API that's mostly public but has a few personalized fields?

Split it: serve the public part from a cacheable endpoint with a short TTL and tag-based purging and fetch personalized fields from a separate uncached endpoint. Avoid putting user cookies into the cache key, which destroys the hit ratio.

Q12. How do you make a system resilient to a CDN outage?

Have a tested failover path: DNS-based switching to a second CDN or directly to the origin, an origin sized (or able to scale) for uncached traffic and status and incident tools that don't depend on the same CDN. Weigh multi-CDN against the extra operational work.

Scenario-based

Q13. After a deploy, some users see the old JavaScript and the site breaks. What happened and how do you fix it for good?

The JS file probably has a fixed name and a long TTL, so some edges (or browsers) still have the old version while the new HTML expects the new one. Short-term, purge the file. Long-term, use fingerprinted file names (app.3f9a1c.js), cache them for a year with immutable and give HTML a short TTL or revalidation, so new HTML always points to new files.

Q14. Your CDN hit ratio dropped from 92% to 60% overnight with no traffic change. How do you investigate?

Check what changed: a deploy that altered Cache-Control or added Vary headers, new query parameters (like campaign tracking), a cookie now included in the cache key or a CDN config change. Compare CF-Cache-Status/X-Cache headers on sample URLs, look at the top missed URLs in CDN logs and check whether the number of unique cache keys jumped.

Q15. Design video delivery for an online learning platform where only paying students can watch.

Store encoded video as HLS or DASH chunks in private object storage, serve them through a CDN with long TTLs (chunks never change) and protect them with signed URLs or signed cookies that expire after a few hours. Exclude the signature parameters from the cache key so all students share cached chunks. Use an origin shield, lock storage to CDN-only access and monitor byte hit ratio and edge errors.

FAQ

1. What is a CDN in system design?

A CDN (Content Delivery Network) is a network of servers in many locations that store copies of your content close to users. In system design, it sits between users and your servers to make responses faster, reduce load on your origin, cut bandwidth costs and protect against traffic spikes and attacks.

2. How does a CDN work?

A user's request is routed to the nearest CDN server. If that server has a fresh cached copy, it answers immediately (a cache hit). If not, it fetches the content from your origin server, stores a copy based on your caching headers and sends it to the user (a cache miss). Later users nearby get the cached copy.

3. What is the difference between a CDN and a cache?

A cache is any place that stores copies of data to serve them faster, like a browser cache or Redis. A CDN is a specific kind of cache: a shared, geographically distributed network of caching servers placed close to users across the internet, usually with extra features like DDoS protection and TLS termination.

4. Does a CDN make a website faster?

Usually yes, especially for users far from your servers, because content travels a much shorter distance and connections are set up with a nearby server. Pages with lots of images, scripts or video benefit most. Personalized content that can't be cached gains less, though TLS termination at the edge still helps.

5. Can a CDN cache dynamic content?

Yes, if the response is the same for many users for at least a short time. Product APIs, popular search results, scores and public pages can be cached with short TTLs. Personalized responses such as carts, orders and account pages should not be cached in a shared CDN cache.

6. What is cache invalidation in a CDN?

Cache invalidation (or purging) removes cached copies before their TTL expires, so users get the updated version. You can purge specific URLs, purge groups of content by tag or avoid purging by publishing changed files under new versioned URLs.

7. What is the difference between a push CDN and a pull CDN?

In a pull CDN, edge servers fetch content from your origin the first time it's requested. In a push CDN, you upload content to the CDN ahead of time. Pull is simpler and most common for websites; push suits large, predictable files like software downloads and video libraries.

8. Is a CDN a single point of failure?

It can be, because so much traffic depends on it. Outages at Fastly in 2021 and Cloudflare in 2019 and 2025 affected many websites at once. You reduce the risk with a tested fallback, such as switching DNS to a second CDN or to your origin and by making sure your origin can handle traffic without the cache.

9. Which CDN is best?

There isn't one best CDN for everyone. Cloudflare, Akamai, Amazon CloudFront, Fastly, Google Cloud CDN and Azure Front Door are all widely used. Choose based on your existing cloud provider, where your users are, the features you need (purging, video, edge code, security) and pricing at your traffic level.

10. How do I explain a CDN in a system design interview?

Say what goes through the CDN and why (static assets with long TTLs, public pages with short TTLs, personal data bypassing the cache), how content stays fresh (versioned URLs and purging), how the origin is protected (shielding, request collapsing, origin locked to CDN traffic) and what happens if the CDN fails. Add a number, like hit ratio, when it supports your point.

Key Takeaways

  • A CDN keeps copies of your content close to users, which makes sites faster, cuts origin load and bandwidth and absorbs spikes and attacks.
  • Distance is the reason it works: a round trip from Mumbai to Virginia takes at least about 128 ms and a new HTTPS connection needs several.
  • Headers control caching. Learn Cache-Control (public, private, no-store, no-cache, max-age, s-maxage, immutable, stale-while-revalidate) and ETags.
  • Version your static files and you'll rarely need to purge.
  • The cache key decides your hit ratio. Keep tracking parameters and unneeded headers out of it.
  • Protect the origin with shielding, request collapsing and an origin that only accepts CDN traffic.
  • Never cache personal data in a shared cache. The Steam incident shows how fast this goes wrong.
  • Plan for CDN failure. Big CDN outages have started with small, valid-looking changes.
  • Watch hit ratio, origin load and edge errors, not just uptime.
Responses (0)

Write a response

CommentHide Comments

No Comments yet.