A CDN feels like magic: your site suddenly loads fast everywhere. But it's really just a handful of well-understood parts working together. Let's take them one at a time.
The one-sentence version
A CDN (Content Delivery Network) is a big fleet of servers spread across the world that keep copies of your files close to your users, so pages load faster.
That's it. Everything below is just why that helps and how they pull it off.
It starts with a domain
Before any of this can happen, your site needs an address. You buy a domain from a registrar (Namecheap, Cloudflare Registrar, GoDaddy) and point it at your host — and how you point it decides how much a CDN can do for you later:
| Way to point the domain | What you set | Who answers DNS afterwards |
|---|---|---|
| DNS records | An A / AAAA record (→ an IP) or a CNAME (→ your host's hostname), set at your registrar | Your registrar's DNS |
| Nameserver delegation | Replace the domain's nameservers with your host's or CDN's | The host / CDN becomes your authoritative DNS |
That second row is the one that unlocks a CDN: when you hand your nameservers over, the CDN becomes your DNS, so it can answer every lookup with the IP of a nearby edge. That's what makes the routing later in this post possible. Right now, though, your domain probably resolves to a single machine: your origin — the server your site actually runs on.
The problem: distance costs time
Say that origin sits in Frankfurt. When someone in Frankfurt visits, it's fast. When someone in Sydney visits, every byte has to physically travel ~16,000 km through cables. Data can't beat the speed of light, so that round trip alone adds real latency, before your server has even done any work. Add TCP (Transmission Control Protocol) handshakes and TLS (Transport Layer Security) negotiation (each a separate round trip), and a far-away user pays that distance tax several times per page.
The insight: most of what a website serves is the same for everyone, that is, JS bundles, CSS, images, fonts. So why fetch them from Frankfurt every time? Put copies near people.
A CDN puts a copy of your content on servers spread around the globe. Here's the core mechanism, which is really about where the request gets answered:
The solid arrows (user ↔ edge) are what happens almost every time. The dashed arrows (edge ↔ origin) happen rarely, usually just the first time anyone in that region requests a file. That's the whole trick. Now let's zoom into each part.
Edge servers and the cache
Those nearby servers are called edge servers (or PoPs, "Points of Presence"). An edge server is basically a reverse proxy with a big cache in front of your origin. When a request arrives, one of two things happens:
| Scenario | What the edge does |
|---|---|
| Cache hit | The file is already stored locally, so it's returned immediately — no trip to origin. |
| Cache miss | The edge doesn't have it, so it fetches from origin once, stores a copy, and serves it. The next user in that region gets a hit. |
So the first visitor in Sydney "warms" the cache, and everyone after them rides for free. This is why CDNs shine for high-traffic static assets: the hit ratio climbs toward ~99%.
Finding the nearest edge
Here's a question that trips people up: when your browser requests cdn.example.com/app.js, how does it end up talking to the Sydney box instead of the Frankfurt one? Two common mechanisms:
| Mechanism | How the nearest edge is chosen | In one line |
|---|---|---|
| DNS-based routing | When your browser resolves cdn.example.com, the CDN's DNS server sees roughly where the request came from (via the resolver's location) and hands back the IP of a close edge. | Same hostname, different answer depending on who's asking. |
| Anycast routing | Many edge servers share the same IP address, and the internet's routing protocol (BGP, Border Gateway Protocol) naturally sends your packets to the "nearest" one in network terms. | You dial one address; the network topology decides which box picks up (Cloudflare leans heavily on this). |
Here's what that first request actually looks like end to end, from resolving the name to warming the cache:
Both mechanisms share the goal — get you to a close edge — but they pick that edge very differently, and the difference bites in two places:
- DNS routing sees your resolver, not you. The CDN's DNS server never sees your browser; it sees whichever recursive resolver you use. If that resolver sits near you, great — but if you're in Sydney using a public resolver whose nearest node is elsewhere, you can be pointed at a sub-optimal edge. The fix is an extension called EDNS Client Subnet (ECS), which forwards a truncated slice of your IP so the CDN can place you accurately.
- Anycast's "nearest" is network-nearest, not kilometre-nearest. BGP chooses a path by routing policy and AS (autonomous system) hops, not physical distance. Usually that lines up with geography, but occasionally the box that's closest on a map isn't the one that answers.
Those differences also decide when each approach shines:
| Dimension | DNS-based routing | Anycast routing |
|---|---|---|
| Failover when an edge dies | — clients keep the cached IP until its time-to-live (TTL) expires | — BGP reroutes to the next PoP |
| Routing control | — you can express per-region and health rules | — BGP decides "nearest," not you |
| Sees the real user location | — only via the resolver (unless ECS is used) | — follows the actual network path |
In practice big CDNs combine both, plus health checks and load metrics, so you're routed to an edge that's close and healthy and not overloaded.
Cache control: the part you actually influence
As a frontend dev, this is where you have real leverage. The edge doesn't guess how long to keep things, you tell it, mostly via HTTP response headers from your origin:
Cache-Control: public, max-age=31536000, immutableon a hashed asset (app.4f3a2b.js) says "cache this for a year, it'll never change." Since the filename changes when the content changes (Vite does this for you), you never have a stale-file problem.Cache-Control: no-cacheor a shortmax-ageonindex.htmlsays "always revalidate," so users pick up new deploys immediately.- The cache key is what the edge uses to decide whether two requests are "the same." By default it's the URL, but it can include things like
Accept-Encoding(so gzip and brotli variants are stored separately). Getting this wrong causes either cache misses or the wrong variant being served.
The classic pattern for a Vite/React SPA (Single-Page Application): hash your assets and cache them forever, keep index.html uncached (or short-lived). Deploys become atomic and instant, and rollbacks are trivial because old hashed files still sit in the cache.
Invalidation is the other half. When you do need to force-evict something, you issue a purge (by URL, by tag, or "purge everything"). The famous saying, attributed to Phil Karlton, is that there are only two hard things in computer science: cache invalidation and naming things. Content-hashed filenames are how you mostly dodge this problem entirely.
Cache misses at scale: tiered caching
One edge isn't one machine, it's a cluster, and there are dozens or hundreds of PoPs. Naively, a brand-new file could miss on every PoP simultaneously and hammer your origin with identical requests (a "thundering herd" or cache stampede). CDNs solve this with:
- Tiered / hierarchical caching: edges don't all go straight to origin. They ask a smaller set of regional "parent" caches first, which then ask origin. Fewer requests reach you.
- Origin shield: you designate one PoP as the single gateway to your origin. Every miss funnels through it, so your origin sees at most one request per unique object, not one per edge.
- Request coalescing: if 10,000 users hit the same cold URL at once, the edge sends one request upstream and makes the rest wait for that single response.
Stacked together, those techniques funnel many edges down to a single request at your origin:
More than a cache: what else the edge does
Modern CDNs do a lot at the edge because the edge is already close to the user and sits in the request path:
- TLS termination: the HTTPS handshake happens at the nearby edge, not across the ocean, which removes several slow round trips.
- Compression and protocol upgrades: brotli/gzip, HTTP/2, HTTP/3 (QUIC), all handled at the edge regardless of what your origin speaks.
- Security: DDoS (Distributed Denial of Service) absorption (that huge distributed capacity soaks up floods), a WAF (Web Application Firewall) filtering malicious requests, and bot management, all before traffic reaches you.
- Edge compute: small functions (Cloudflare Workers, Lambda@Edge, Fastly Compute) run at the edge, so you can do redirects, A/B splits, auth checks, personalization, or even render pages geographically close to users, with almost no latency cost. This is the backbone of a lot of modern SSR (Server-Side Rendering) / edge-rendering setups.
Real-world examples: same parts, different wiring
Here's the reassuring part: every production CDN is just "several DNS services + several reverse-proxy servers" — the same setup a hosting provider might already run. What separates them is how the DNS layer chooses an edge (the two routing mechanisms we saw earlier) and why there's more than one DNS provider (resilience). Let's ground the whole post in real stacks.
The big commercial CDNs pick edges in opposite ways. Akamai leans on DNS-based routing, Cloudflare and Fastly on Anycast — same building blocks, different routing philosophy:
| CDN | DNS layer | Reverse-proxy layer | How the nearest edge is chosen |
|---|---|---|---|
| Akamai | Steering DNS that answers per-user | ~4,000 cache locations | DNS-based routing — its mapping system picks a good edge for you and returns that IP |
| Cloudflare | Anycast DNS | 300+ identical PoPs (Pingora, their own Rust proxy) | Anycast — every PoP shares an IP; BGP routes you to the closest |
| Fastly | Anycast DNS | Varnish-based edges programmed in VCL (Varnish Configuration Language) | Anycast, like Cloudflare |
The AWS-native stack is probably closest to a typical hosting service, and maps one-to-one onto that DNS-plus-proxies description:
- DNS services: Route 53 with latency or geo routing, often paired with a second provider like NS1 for resilience.
- Reverse proxies: CloudFront (the caching edge) in front of Application Load Balancers (ALBs — themselves reverse proxies) across multiple regions.
The self-hosted multi-region stack is the do-it-yourself version — and, honestly, a real mini-CDN:
- DNS: GeoDNS (a DNS server that returns a region-specific IP) via PowerDNS or NS1.
- Reverse proxies: nginx, HAProxy, or Varnish boxes in a few regions, each caching static assets and proxying misses to origin.
The only things separating this from Akamai are scale and how clever the steering is.
Multi-CDN is the maximal version — several DNS services steering across several reverse-proxy fleets — and it exists for a hard-learned reason. On 21 October 2016, a DDoS attack on a single DNS provider (Dyn) knocked Twitter, Reddit, Spotify, and GitHub offline. The industry's response was to stop depending on one DNS service:
A traffic manager measures real-user performance and steers each visitor to whichever CDN is fastest and healthiest at that moment — so no single DNS provider or proxy fleet is a single point of failure.
The one-paragraph synthesis
A CDN answers the question "how do I serve the same bytes to everyone in the world quickly and cheaply?" by pushing cached copies of your content onto a global mesh of edge servers, routing each user to a close one via DNS and Anycast, respecting the cache lifetimes you set through HTTP headers, shielding your origin from redundant traffic through tiered caching, and increasingly running security and compute logic at that edge too. As a frontend developer, your main levers are content-hashing your build output, setting sane Cache-Control headers (immutable for hashed assets, short-lived for your HTML entry point), and knowing how to purge when you must.
Each of these pieces is worth a post of its own — configuring Cache-Control for a Vite build, or how edge functions reshape SSR / RSC (React Server Components) deployment, are the two I'd reach for next.
