DNS, CDNs, and the edge
How a name becomes an address, how that address leads to a server a few milliseconds from the user instead of an ocean away, and what code and files a frontend should run and keep there.
The problem: the speed of light is too slow
Picture a small team in Frankfurt that builds a recipe site. Their one server sits in a data centre in Frankfurt. For the team, the site feels instant: the HTML arrives in 40 ms. Then a food blogger in Sydney shares a link, and 50,000 Australians open it in an hour.
For each of them the page takes more than two seconds before anything shows. The server is not slow. The code is not slow. The problem is the 16,500 km between Sydney and Frankfurt, which every request has to cross twice: once there and once back.
Round trip math
Light in optical fibre travels at about 200,000 km per second, roughly two thirds of its speed in a vacuum. That is about 200 km per millisecond. Cables do not follow straight lines, and routers add their own delay, so real paths are often 1.5 to 2 times slower than the straight-line number.
An RTT (round trip time) is the time for a packet to go to the server and for the answer to come back. Sydney to Frankfurt is about 16,500 km one way. The floor is 2 x 16,500 / 200 = 165 ms, and the real RTT is usually around 250 to 300 ms. No amount of money buys a faster speed of light.
One RTT would be fine. The trouble is that loading a page needs many of them, one after the other. Before the first byte of HTML arrives, the browser needs a DNS lookup, a TCP handshake (one RTT), a TLS handshake (one more RTT with TLS 1.3), and the HTTP request itself (one more RTT). That is three to four RTTs before TTFB, the time to the first byte of the response.
| Step | User in Frankfurt (RTT 10 ms) | User in Sydney (RTT 280 ms) |
|---|---|---|
| DNS lookup (cached at the resolver) | about 5 ms | about 5 ms |
| TCP handshake: 1 RTT | 10 ms | 280 ms |
| TLS 1.3 handshake: 1 RTT | 10 ms | 280 ms |
| HTTP request and first byte: 1 RTT plus server time | 10 ms + 20 ms | 280 ms + 20 ms |
| TTFB | about 55 ms | about 865 ms |
And TTFB is only the start. The HTML names a stylesheet and scripts on the same host (cheap now, the connection is open, but still one RTT each round), then fonts and images. A page with three rounds of requests pays the Sydney RTT at least three more times. Two seconds is easy to reach.
Three tools that fix it
The web solves the distance problem with three layers that work together. This lesson covers all three, in the order a request meets them.
- DNS, the Domain Name System, turns a name like
recipes.exampleinto an IP address. It is also the first place where a provider can steer the user to a nearby server. - A CDN, a content delivery network, is a set of servers in hundreds of cities, called PoPs (points of presence). The user's connection ends at the nearest PoP, so handshakes cost a 10 ms RTT, not a 280 ms one, and cached files never cross the ocean at all.
- The edge means running your own code on those PoPs: small functions that redirect, rewrite, check a cookie, pick an A/B variant, or even render HTML, a few milliseconds from the user.
Earlier lessons covered parts of this. From URL to pixels walked through the DNS lookup and handshakes once. HTTP caching and CDN caching covered the headers and rules that decide what a cache may keep, and for how long.
This lesson does not repeat those rules. It covers how the network finds a nearby server, what happens there, and what a frontend should put on it.
Check your understanding · Exercise 1
A user in Singapore loads a site whose only server is in Virginia, about 15,500 km away. Which statements are true? Select all that apply.
How DNS turns a name into an address
Computers on the internet find each other by IP address, like 203.0.113.7 (IPv4) or 2001:db8::7 (IPv6). People use names. DNS is the global, distributed phone book that maps one to the other. No single server holds the whole book: it is split into a tree, and each part is run by whoever owns that part of the name.
The four servers in a lookup
Read a name from right to left and you walk down the tree. www.recipes.example sits under recipes.example, which sits under example, which sits under the root (an invisible dot at the end). Four kinds of servers take part in a lookup.
- Stub resolver: a small library in the operating system. It does not walk the tree. It asks one configured resolver and waits. The browser talks to it, or, with DNS over HTTPS turned on, skips it and asks a resolver directly.
- Recursive resolver: the server that does the real work, run by the internet provider, the company network, or a public service like
1.1.1.1or8.8.8.8. It walks the tree on the user's behalf and caches every answer it gets, for every user it serves. - Root and TLD servers: the root servers know only who runs each top-level domain (TLD) such as
.com,.org, or.io. The TLD servers know only which name servers are in charge of each domain under them. There are 13 root server names,atom, but each is served from many places: well over a thousand sites worldwide. - Authoritative server: the server that holds the real records for your domain. It is run by your DNS provider (Route 53, Cloudflare DNS, NS1, your registrar). Its answers are the truth; everyone else only caches them.
A cold lookup, step by step
Say nobody has looked up www.recipes.example for a while, so no cache has it. Here is the walk, with typical times for a resolver in the same city as the user.
- The browser checks its own small cache, then asks the stub resolver, which checks the OS cache. Both miss. The stub sends one UDP packet to the recursive resolver (about 5 to 20 ms on a home connection).
- The resolver asks a root server: who runs
.example? The root answers with a referral, a list of TLD name servers. The resolver almost always has this cached already, because the TTL on TLD referrals is two days. - The resolver asks a
.exampleTLD server: who runsrecipes.example? Another referral, this time tons1.dnsprovider.netand the other name servers of your DNS provider. Often cached too. - The resolver asks the authoritative server for
www.recipes.example. The answer is aCNAMEpointing atrecipes.cdn-provider.net, a name the CDN owns. - The resolver now has to resolve that new name, which may need its own walk to the CDN's authoritative servers. They answer with an
Aand anAAAArecord for a nearby PoP. - The resolver caches every answer for its TTL and sends the final addresses back to the stub, which gives them to the browser.
A fully cold lookup like this can take 100 to 300 ms. In practice it is rare for a popular site: the resolver serves thousands of users, so the answer is usually in its cache and the lookup costs one short trip to the resolver.
The records a frontend meets
| Record | What it holds | Example | Where you meet it |
|---|---|---|---|
A / AAAA | An IPv4 / IPv6 address | 203.0.113.7 | The final answer the browser connects to. |
CNAME | Another name to look up instead | www to recipes.cdn-provider.net | Pointing your host name at a CDN or a hosting platform. |
NS | The name servers in charge of a domain | ns1.dnsprovider.net | Moving your domain to a new DNS provider. |
HTTPS | Connection hints: protocols, ports, address hints | alpn="h2,h3" | Letting the browser use HTTP/3 on the first visit. |
TXT | Free text | v=spf1 ..., verification tokens | Proving you own the domain to a CDN or certificate authority. |
One trap: a CNAME is not allowed at the apex, the bare domain recipes.example, because the apex must also hold NS and other records, and a CNAME cannot sit next to anything else. DNS providers work around it with a non-standard feature, called ALIAS, ANAME, or CNAME flattening, which resolves the target on their side and returns plain A and AAAA records. If a CDN setup guide asks for a CNAME on the apex, this is the feature you need.
TTLs: how long an answer may be cached
Every record carries a TTL, time to live, in seconds. A resolver that got an answer with TTL 300 may hand it out for up to five minutes without asking again. TTLs are the whole reason DNS is fast and cheap, and the whole reason DNS changes are slow.
$ dig www.recipes.example
;; ANSWER SECTION:
www.recipes.example. 3600 IN CNAME recipes.cdn-provider.net.
recipes.cdn-provider.net. 60 IN A 198.51.100.20
recipes.cdn-provider.net. 60 IN AAAA 2001:db8:20::1
;; Query time: 14 msec
CNAME, which rarely changes, and a short TTL on the CDN's addresses, so the CDN can move traffic quickly.- Long TTLs (an hour to a day) mean fewer lookups and less load on your DNS provider, but any change takes up to that long to reach everyone.
- Short TTLs (30 to 300 seconds) let you move traffic fast, at the cost of more lookups. CDNs use short TTLs on their own records for exactly this reason.
- TTLs count down in every cache. A resolver that cached the answer 50 minutes ago hands it out with 10 minutes left, and the browser and OS cache it for at most that long.
Negative caching: remembering that a name does not exist
Resolvers also cache failures. If a name does not exist, the authoritative server says NXDOMAIN, and the resolver remembers that answer. How long is set by the SOA (start of authority) record of the zone: the smaller of the SOA record's own TTL and its minimum field, per RFC 2308. Common values run from a few minutes to an hour, and many resolvers also cap it at a few hours.
This bites during launches. Someone tests beta.recipes.example before the record exists, the resolver caches NXDOMAIN for an hour, and when the record is created five minutes later, everyone behind that resolver still gets an error. Create records before anyone looks them up, and check the SOA negative TTL first.
Check your understanding · Exercise 2
Your www record has TTL 3600. At 10:00 you change it to a new address. Which statements are true? Select all that apply.
Finding the nearest PoP: DNS steering and anycast
A CDN has PoPs in hundreds of cities. A user in Mumbai should land in the Mumbai PoP, not in London. Something has to make that choice for every new connection, with no help from the user. CDNs use two methods, often together: answer differently in DNS, or give every PoP the same address and let the internet's routers pick.
DNS-based steering
With DNS steering (often called GeoDNS), each PoP has its own IP addresses. The CDN runs the authoritative servers for its own names, like recipes.cdn-provider.net. When a resolver asks, the CDN looks at where the question comes from and answers with the addresses of a PoP near it. Mumbai resolvers get Mumbai addresses; Paris resolvers get Paris addresses.
The catch: the CDN sees the address of the resolver, not the user. That is fine when the resolver is the user's internet provider in the same city. It goes wrong when the user picks a public resolver whose nearest site is in another country, or a company routes all DNS through its head office. The CDN then picks a PoP near the resolver, which may be far from the user.
The fix is EDNS Client Subnet (ECS, RFC 7871): the resolver passes along a shortened form of the user's address, such as the first 24 bits of an IPv4 address, so the CDN can pick by the user's network. Some resolvers send it, some do not, on purpose, because it leaks a little about the user to every authoritative server. Steering works best with it, and still works without it, just less precisely.
DNS steering has one big strength: the CDN can change its answer at any moment, for any reason. It can send users away from a PoP that is overloaded, or toward a cheaper one, or measure real latency from each network and pick the fastest PoP, not just the closest on the map. The price is that each change only takes effect when cached answers expire, which is why CDN records often have TTLs of 20 to 60 seconds.
Anycast
With anycast, every PoP announces the same block of IP addresses to the internet. The routers that join networks together share routes with BGP, the Border Gateway Protocol, and each router forwards a packet along the shortest route it knows to that address. Since many PoPs claim it, each user's packets end up at whichever PoP is closest in network terms. One address, hundreds of places.
Anycast has three strong points. DNS stays simple: every user gets the same answer, so resolver location does not matter. Failover is fast: if a PoP goes down, it stops announcing the route, and usually within seconds routers send its users to the next nearest one, with no TTL to wait out.
And attacks get spread out: a flood of traffic from bots around the world is split across every PoP instead of piling onto one. That is why the DNS root servers and public resolvers like 1.1.1.1 and 8.8.8.8 are anycast too.
The weak points: "closest in network terms" is not always closest on the map. BGP picks routes by the number of networks crossed and by the business deals between them, not by milliseconds. A user can sometimes land in a PoP one country over because their provider's cheapest route goes there. And the CDN has less fine control: it cannot easily move one city's users to a different PoP without changing route announcements, which affects everyone near that PoP.
People sometimes worry that a route change in the middle of a TCP connection will send the next packet to a different PoP that knows nothing of the connection. It can happen, but routes are stable enough that for short web requests it is rare, and large anycast networks have tooling to handle it. Long-lived connections like WebSockets need to reconnect gracefully anyway.
Decision How should a CDN send each user to a nearby PoP?
What we pick: As a frontend engineer you rarely choose this: it comes with the CDN. What you should know is which kind yours uses, because it changes how failover behaves (seconds with anycast, a TTL with DNS steering) and why a user might see a far PoP (their resolver, or their provider's routing). Cloudflare is built on anycast; Akamai is known for DNS-based mapping; most large CDNs mix both in some form.
Check your understanding · Exercise 3
A user in Lisbon uses a public DNS resolver whose nearest site is in Madrid. Which statements are true? Select all that apply.
What happens inside a PoP
A PoP is not one server. It is a rack or a room of them in a data centre that connects to many local networks: load balancers in front, a fleet of machines that end connections and run code, and caches in memory and on fast SSDs. When the user's packets arrive, three things happen in order: the PoP ends the connection, checks its cache, and if needed, asks the next layer up.
TLS ends at the edge
TLS termination means the PoP, not your server, completes the TLS handshake with the browser. The CDN holds a certificate for your domain (one it issues for you, or one you upload) and decrypts the request in the PoP. This is what makes a CDN help even when nothing is cached: the slow handshakes now cost the short user-to-PoP RTT.
The PoP then sends the request on to your server, the origin, over a second connection. That connection is not new for each user. The PoP keeps a pool of warm, already-encrypted connections to the origin and reuses them for thousands of requests. So the long distance is crossed once per request, not three or four times.
| Step | Sydney user, Frankfurt origin, no CDN | Sydney user, Sydney PoP, cache miss | Sydney PoP, cache hit |
|---|---|---|---|
| TCP handshake | 280 ms | 10 ms | 10 ms |
| TLS 1.3 handshake | 280 ms | 10 ms | 10 ms |
| Request to the PoP and back | (none) | 10 ms | 10 ms |
| PoP to origin and back, warm connection | (none) | about 270 ms | (none) |
| Request to the origin and back | 280 ms | (counted above) | (none) |
| Server time | 20 ms | 20 ms | about 1 ms |
| TTFB (plus about 5 ms of DNS) | about 865 ms | about 325 ms | about 35 ms |
Ending TLS at the edge has two security costs that you should say out loud in a design. First, the CDN sees your traffic in plain text, cookies and all, so it is part of your trust boundary. Second, the hop from the PoP to the origin needs its own TLS with a certificate the CDN checks; a setting like "encrypt to the browser only" leaves that hop open on the public internet.
Also lock the origin down so it only accepts traffic from the CDN: an allowlist of the CDN's address ranges, a secret header the CDN adds, mutual TLS, or a private tunnel. Otherwise an attacker who finds the origin's address skips the CDN entirely, along with its cache, its rate limits, and its firewall.
Cache hit ratio
Once the request is decrypted, the PoP looks it up in its cache. The cache hit ratio is the share of requests answered from cache: hits divided by all requests. It is the single number that says how much a CDN is helping, both for user speed and for origin load.
Small changes in the ratio are big changes in origin load. At 20,000 requests per second, a 95 percent ratio sends 1,000 requests per second to the origin. At 99 percent, it sends 200: five times fewer, from a four point change. Think of it as the miss ratio: going from 5 percent misses to 1 percent divides the origin's work by five.
There are two ways to count it. The request hit ratio counts requests; the byte hit ratio counts bytes. A site can have a 98 percent request ratio because small icons hit, while its big videos miss and most of its bandwidth still comes from the origin. Check both.
Why does the ratio drop? Cache keys that split one file into many copies, Vary on per-user headers, short TTLs, and purging everything on deploy: the CDN caching lesson covers those rules and how to fix them. Here, one cause matters most: the more PoPs, the fewer requests each one sees.
A file asked for 1,000 times an hour, spread over 300 PoPs, reaches most PoPs a few times an hour. Each PoP misses once before it can hit, and may drop rarely used files to make room. Low-traffic and long-tail content suffers most.
Origin shielding and request collapsing
The answer to many PoPs each missing is a second tier. With origin shielding, a PoP that misses asks one chosen cache, the shield, instead of the origin. The shield is a large PoP near your origin. Tiered caching is the wider name for any such second layer, such as regional caches.
Only the shield talks to the origin, so a new file costs the origin about one request, not one per PoP. The shield's own hit ratio is high, because it sees the misses of every PoP below it.
Request collapsing handles the burst case. If 2,000 users ask the same PoP for a just-deployed file in the same second, the PoP sends one request upstream and makes the other 1,999 wait for that answer, instead of sending 2,000. Shields collapse requests across PoPs the same way.
Check your understanding · Exercise 4
A site serves 10,000 requests per second through a CDN with a 96 percent hit ratio. Which statements are true? Select all that apply.
Lab: where the milliseconds go
The numbers so far follow one formula. It is worth learning, because in an interview you can rebuild any latency estimate from it in a few seconds.
TTFB = DNS
+ 1 RTT(user, PoP) TCP handshake
+ 1 RTT(user, PoP) TLS 1.3 handshake
+ 1 RTT(user, PoP) the request itself
+ on a miss: RTT(PoP, shield or origin) + server time
+ on a hit: about 1 ms of cache lookup
RTT(user, x) is about 10 ms + 2 x distance / (200 km per ms) x 1.65
(10 ms of last mile; real routes are about 1.65 times the straight line)
RTT(PoP, origin) is the same without the 10 ms: PoPs sit on fast backbone links
Try it below. Pick where the user is, where the nearest PoP is, and where your origin lives. Then switch between a cache hit and a miss, and between a CDN and none. Watch which bar grows.
What the lab shows
- Handshakes dominate far from the origin. Without a CDN, a user 15,000 km away spends most of the TTFB on handshakes, not on the server.
- A CDN halves even uncached responses. Ending TLS nearby turns three long trips into one long trip plus three short ones.
- A hit makes distance to the origin irrelevant. The origin can be anywhere when the response is cached.
- Origin placement matters for misses. If most users are in Asia, an origin in Singapore cuts every miss for them. That is a backend decision you can argue for from the frontend numbers.
- A far PoP wastes the CDN. A PoP 2,000 km away, from bad steering, adds about 30 ms to every round trip, so about 100 ms to TTFB. For a user near the origin, that can be slower than no CDN at all.
Think first
A Sydney user has a 10 ms RTT to the local PoP. How much does HTTP/3 save on TTFB for a cache hit, and how much would it save without a CDN, with a 280 ms RTT to Frankfurt?
HTTP/3 merges the transport and TLS handshakes into one round trip, so it saves one RTT on a new connection.
At the PoP that is about 10 ms, out of a TTFB of about 35 ms. Without a CDN it is about 280 ms out of about 865 ms. Protocol upgrades help most where RTTs are long, which is also where a CDN helps most. Both together give the best result, and most CDNs offer HTTP/3 at the edge with one setting.
Edge compute: running your code in the PoP
For years a CDN could only store and serve files. Today most CDNs also run your code in their PoPs, on every request, before the cache or instead of the origin. This is edge compute, and the small functions are called edge functions, workers, or middleware, depending on the vendor.
The main platforms
| Platform | Runs on | Where | Good to know |
|---|---|---|---|
| Cloudflare Workers | V8 isolates, Web APIs like fetch, Request, Response | Every Cloudflare PoP | Isolates start in milliseconds, so cold starts are close to zero. Limits on CPU time and memory per request. |
| Vercel Routing Middleware and Functions | Node.js by default (Fluid compute); an edge runtime is still offered | Middleware globally; functions in the regions you pick | Middleware runs before the cache. In Next.js 16 its file is proxy.ts (formerly middleware.ts). Vercel now recommends Node.js over the edge runtime for most code. |
| Netlify Edge Functions | Deno, Web APIs | Netlify's edge network | TypeScript out of the box; same Request and Response model. |
| Amazon CloudFront Functions | A small JavaScript runtime | Every CloudFront edge location | Sub-millisecond work on headers, URLs, and cookies. No network calls, no body access, and at most 10 KB of code. |
| Amazon Lambda@Edge | Node.js or Python | CloudFront's regional edge caches | Full Lambda with network access, but real cold starts and fewer locations. |
| Fastly Compute | WebAssembly | Every Fastly PoP | Compile from Rust, Go, JavaScript and others. |
Two designs sit behind these products. Isolate-based runtimes (Workers, Vercel's and Netlify's edge runtimes) run many customers' code inside one process, each in its own sandbox, like tabs in a browser. Starting one costs milliseconds, so cold starts barely matter, but you get Web APIs only, a memory cap (128 MB on Workers), and a CPU time budget per request.
Container or VM-based runtimes like Lambda@Edge run full Node.js with more freedom. The price is the cold start: a new instance can take a few hundred milliseconds to start, which is a lot to add to a request you wanted to make fast.
Good jobs for the edge
The best edge jobs are quick decisions that need only the request itself: its URL, headers, cookies, and the country the CDN detected. No database, no slow API.
- Redirects and rewrites:
/old-pricingto/pricing,/to/en-gb/byAccept-Languageor country, or serving/blogfrom a different origin. - Auth gates: no session cookie on
/app/*, redirect to/loginbefore the origin is touched. Verifying a signed token (a JWT checked with a public key) works too, since it needs no database. - A/B tests and feature flags: read or set a group cookie, then fetch the cached variant for that group. Both variants stay cacheable, and the user never sees a flicker of the wrong one.
- Headers: add security headers like CSP and HSTS, or set the cache key for a request.
- Personalising cached HTML: fetch the cached page and stream it through an HTML rewriter that fills in a small part, like the user's name or currency.
- Bot and abuse checks: rate limits and blocks before the request costs origin CPU.
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
if (url.pathname !== "/") return fetch(request);
const cookie = request.headers.get("Cookie") ?? "";
const known = cookie.match(/ab-home=(a|b)/)?.[1];
const group = known ?? (Math.random() < 0.5 ? "a" : "b");
// Each variant is its own URL, so the CDN caches both.
url.pathname = `/home-${group}`;
const page = await fetch(new Request(url, request));
const response = new Response(page.body, page);
if (!known) {
response.headers.append("Set-Cookie", `ab-home=${group}; Path=/; Max-Age=2592000`);
}
return response;
},
};
The trap: your data is not at the edge
Edge code is close to the user, which means it is far from your database. Say an edge function in Sydney renders a product page and makes three queries, one after another, to a database in Virginia. Each query is a 230 ms round trip: almost 700 ms before the HTML can start. The same code on a server next to the database pays 1 ms per query, and only one long trip back to the user, through the CDN.
This is why platforms that pushed "render everything at the edge" have moved back toward regional servers for data-heavy work. The fixes are: keep data work at the origin; use data that is replicated to the edge (key-value stores, read replicas), accepting that it may be a little stale; or let the platform run the function near the data (Cloudflare calls this Smart Placement).
Decision A request needs some logic before it gets its response. Where should that logic run?
What we pick: Use the edge for decisions made from the request alone: redirects, auth gates, A/B buckets, headers, geography. Keep anything that talks to a database near the database. Use the browser for what depends on browser state. A good design often uses all three for one page.
Check your understanding · Exercise 5
Which of these are good fits for an edge function? Select all that apply.
What a frontend should put on a CDN
Short answer: put the whole site behind the CDN, and decide per type of response what the CDN may keep. Even responses that can never be cached gain from the CDN: TLS ends nearby, the connection to the origin is warm, and attacks are absorbed before they reach you. The question is not "CDN or not" but "cached for how long, and by whom". The HTTP caching lesson covers the headers; here is the map.
By type of response
| Response | Cached at the CDN? | Typical policy | Why |
|---|---|---|---|
Hashed JS, CSS, and fonts, like app.3f9a1c.js | Yes, for a long time | A year, immutable | A new build gets a new name, so a copy never goes stale. |
| Images and video | Yes | Long if hashed; days if not | Most of the bytes; the biggest bandwidth win. Often through an image CDN that resizes per device. |
| HTML of public pages | Yes, briefly, or revalidated | Seconds to minutes at the CDN, with stale-while-revalidate | Must change soon after a deploy, because it names the new hashed files. |
| Public API reads, like a product list | Yes, briefly | A few seconds to a minute | Even 10 seconds of caching absorbs a traffic spike. |
| Pages and data for one signed-in user | No | private or no-store | A shared cache must never serve one user's data to another. |
Writes: POST, PUT, DELETE | No | Passed through | Still gains from the nearby TLS end and the warm origin connection. |
One host name, many origins
With HTTP/1.1, sites split files across static1.example, static2.example and so on, to open more parallel connections. With HTTP/2 and HTTP/3, one connection carries everything, and every extra host name costs a DNS lookup, a TCP or QUIC handshake, and a TLS handshake. Today the better default is one host name for the page and its assets, with the CDN routing paths to different origins behind it: /assets/* to a storage bucket, /api/* to the API, everything else to the SSR server.
One host also keeps cookies and CSP simple and means the browser can reuse the connection it opened for the HTML. The exceptions are big, separate services like an image or video CDN, where a second host is worth it; add preconnect for that host so its handshakes start early.
Public library CDNs are not a shortcut any more
An old tip was to load React or jQuery from a public CDN, so users who had visited another site using the same file would already have it cached. That stopped working around 2020: Chrome, Safari, and Firefox now partition the HTTP cache by the top-level site, so a file cached while visiting site A is not reused on site B.
So a public library CDN today only adds a new host name (DNS, handshakes) and a new party you must trust. Bundle libraries with your own code and serve them from your own CDN. If you must load a third-party script, pin the version and add integrity (Subresource Integrity), so the browser refuses the file if its contents change.
Check your understanding · Exercise 6
A news site puts everything behind a CDN. Which policies are sound? Select all that apply.
When it breaks: failure modes, migrations, and multi-CDN
DNS and the CDN sit in front of everything. When they fail, the whole site fails, no matter how healthy the servers behind them are. They also fail in ways that are hard to see from your own laptop, because your resolver and your PoP are not your users' resolvers and PoPs.
DNS migrations and long TTLs
The classic mistake: a team moves to a new CDN on Friday evening by changing the CNAME. The record had TTL 86400, a full day. Users whose resolvers cached the old answer keep going to the old CDN for up to a day, and the team switched the old one off at 18:05. For hours, a large share of traffic fails, and there is no way to purge the world's resolvers.
The safe plan works with TTLs instead of against them.
- Lower the TTL early. At least one old TTL before the move (a day ahead for
86400), change the TTL to 60 seconds. Now every cache that refreshes picks up the short TTL. - Run both in parallel. Set up the new CDN fully and test it with a hosts-file entry or a test host name. Both old and new must serve the site correctly.
- Switch. Change the record. Within about a minute most users move.
- Wait, then retire. Keep the old setup running for days, not minutes. Some resolvers raise very low TTLs to a minimum of their own, and some long-running clients (old Java apps, some IoT devices) cache addresses far longer than told.
- Raise the TTL again once the move is stable, to cut lookups.
Moving to a new DNS provider is slower still, because the NS records live in the TLD zone, often with a two-day TTL that you do not control. Run the old and new providers with identical records for at least that long.
Provider outages
- DNS provider outage. In October 2016 a huge DDoS (distributed denial of service) attack on the DNS provider Dyn made many big sites unreachable for hours in parts of the world, though their servers were fine. The fix is two DNS providers, both listed in your
NSrecords and serving the same zone, so resolvers try the other when one fails. - CDN outage. In June 2021 one customer's valid configuration change set off a hidden software bug at Fastly: about 85 percent of its network returned errors, and many major news and government sites went down with it until most of the network recovered within 49 minutes. In July 2019 a single bad firewall rule made Cloudflare's servers spend their CPU on a regular expression and fail requests worldwide for 27 minutes. One provider is one point of failure.
- Your own edge code. A bug in an edge function or a CDN rule ships to every PoP within seconds. That is a global outage you caused. Roll edge changes out gradually where the platform allows it, and keep a fast rollback.
- Origin outage. If the origin is down, the CDN can still serve what it has.
stale-if-errorlets cached pages keep working for a while, so a static marketing site can survive a full origin outage. - Certificate expiry. Managed edge certificates renew themselves; a certificate you uploaded by hand does not. Put the expiry date in monitoring.
Multi-CDN and failover
Large sites use two or more CDNs at once. A DNS layer in front, often a traffic steering service with health checks, decides which CDN each user gets. If one CDN fails health checks, the DNS answers switch to the other, within a short TTL. Some sites also split traffic by region or by price, sending each country to whichever CDN measures fastest there.
Decision Should the site use one CDN or several?
What we pick: Most products should run one good CDN and spend the effort on short TTLs, stale-if-error, and a tested origin. Multi-CDN pays off when an hour of downtime costs more than a team's time to keep two setups in step: large media, retail, and payments sites. If you go multi-CDN, keep edge logic small and portable.
How you notice and debug
dig +short www.recipes.examplefrom several networks, or a public multi-location DNS checker, shows what different resolvers see and with how much TTL left.curl -sIshows the CDN's response headers: a cache status likex-cache: HITorcf-cache-status: MISS, theageof the cached copy, and often which PoP answered.Server-Timingheaders from the edge and origin let real-user monitoring split TTFB into edge time and origin time.- Real-user monitoring grouped by country and by PoP shows a bad PoP or bad steering that synthetic tests from one city miss.
Check your understanding · Exercise 7
You must move www from CDN A to CDN B. The CNAME has TTL 43200 (12 hours). Which steps are right? Select all that apply.
In real products
Every big site uses these pieces, but they arrange them differently, depending on what they serve and where their users are.
- Cloudflare runs one anycast network in more than 330 cities. Every customer's site is reachable from every PoP, and Workers run in all of them. Its public resolver
1.1.1.1is anycast on the same network, which is why it answers in a few milliseconds from most places. - Netflix goes one step closer than a PoP. Its Open Connect program places cache servers inside internet providers' own networks, filled overnight with the shows people in that area are likely to watch. Most video bytes never cross the wider internet at all.
- Wikipedia serves readers from a few caching data centres on several continents, while its databases and editing live in the US. Most page views are anonymous reads, so the hit ratio is very high; signed-in users mostly skip the page cache and get pages built for them.
- Next.js on Vercel shows the frontend view: hashed files under
/_next/static/get year-long caching at the edge, statically generated and ISR (incremental static regeneration) pages are served from the edge cache, the middleware file (proxy.tssince Next.js 16,middleware.tsbefore) runs before the cache for redirects and auth, and server rendering that needs data runs in a region near the database. - Video streaming in general (HLS and DASH) splits video into small segment files, a few seconds each, with fixed URLs. To a CDN, a live stream is just a fast stream of new, cacheable files: one origin fetch per segment per shield, then millions of hits.
The common shape
Look past the brand names and the same layout repeats. DNS with a short TTL points at a CDN. The CDN ends TLS near the user, runs a little request logic, and answers most static requests from cache.
A shield protects the origin. Data-heavy work happens in one or a few regions near the data, and the CDN carries even those responses over warm connections. When you draw a frontend architecture, this is the default to start from and then adjust.
Think first
A startup with users only in India hosts everything in a US region. Their pages are slow in India. They ask whether to move to edge rendering. What do you suggest?
First put a CDN in front, if there is none: TLS ends in India, hashed assets and images are cached there, and uncached HTML pays one long trip instead of three or four. That alone often halves TTFB.
Then look at where the data lives. If all users are in India, the bigger win is moving the origin and database to a region in India, so even misses are short. Edge rendering against a US database would make things worse, not better. Keep the edge for redirects and auth checks.
Using it in a system design interview
Frontend system design interviews rarely ask "explain DNS" on its own. These ideas come up inside a bigger design: a news site, an e-commerce page, a video player, a global dashboard. Bringing them up at the right time, with numbers, shows that you think about the user's whole request, not only the components.
When to bring it up
- When the prompt says global users or names countries: talk about RTT, a CDN, and where the origin should live.
- When you discuss performance or Core Web Vitals: a CDN is the first fix for TTFB, and TTFB is the floor under LCP (Largest Contentful Paint).
- When you choose a rendering strategy: static and ISR pages live at the edge; SSR pages need a region near the data; middleware runs in between.
- When the design has personalised pages: explain how you keep the shared part cacheable and move the personal part to the edge or the client.
- When asked about reliability: DNS TTLs,
stale-if-error, and, for a very large product, multi-CDN.
What to draw
One line of boxes is enough: browser, DNS, CDN PoP (with "TLS, cache, edge logic" written inside), shield, origin (SSR and API), database. Then write the cache policy next to each kind of response: hashed assets for a year, HTML for seconds with revalidation, API reads for a few seconds, personal data private. Add one RTT number for a far user, with and without the CDN.
| Level | What a strong answer includes |
|---|---|
| Junior | Static files on a CDN with hashed names and long caching; knows that a nearby server is faster and why. |
| Mid | RTT math for a far user; TLS ending at the edge; HTML vs asset caching; hit ratio and what lowers it; what not to cache. |
| Senior | Anycast vs DNS steering and their failover; shielding; edge vs regional compute and data gravity; TTL plans for migrations; multi-CDN trade-offs; monitoring TTFB by PoP. |
Check your understanding · Exercise 8
An interviewer asks how you would make a product page fast for users worldwide. Which points belong in a strong answer? Select all that apply.
Summary
- Distance sets a floor: about 1 ms of RTT per 100 km, and every handshake costs one RTT. A far user pays it three or four times before TTFB.
- DNS walks from the stub to a recursive resolver, which asks root, TLD, and authoritative servers and caches each answer for its TTL, including "does not exist" answers.
- CDNs send users to a nearby PoP by DNS steering, anycast, or both. Anycast fails over in seconds; DNS steering waits on TTLs.
- Ending TLS at the PoP and reusing warm origin connections makes even uncached responses much faster. Lock the origin so only the CDN can reach it.
- Hit ratio drives origin load: 95 to 99 percent is five times fewer origin requests. Shielding and request collapsing protect the origin as PoPs multiply.
- Edge functions are for quick decisions from the request alone. Data-heavy work belongs near the data.
- Put the whole site behind the CDN; cache hashed assets for a year, public HTML briefly, and personal data never.
- Lower DNS TTLs before any migration and keep the old target running for days; consider a second DNS provider or CDN only when downtime costs justify it.
In the interview
Questions interviewers ask about this. Answer each out loud first, then compare.
Question 1
Walk me through what happens when a browser resolves www.shop.example for the first time.
The browser and OS caches miss, so the stub resolver asks the configured recursive resolver. If the resolver has no cached answer, it asks a root server for the .example servers, asks those for the shop.example name servers, and asks the authoritative server for www. Root and TLD referrals are usually cached already.
The answer is often a CNAME to the CDN's name, which the resolver resolves too, getting A and AAAA records for a nearby PoP. Every answer is cached for its TTL, and "does not exist" answers are cached as well, for the zone's negative TTL. A warm lookup costs one trip to the resolver; a cold one can cost 100 ms or more.
Question 2
How does a CDN make a page faster for a far-away user when the HTML cannot be cached?
TLS ends at the nearby PoP. The TCP and TLS handshakes cost the short user-to-PoP RTT, and the PoP forwards the request to the origin over a warm connection it already holds. The long distance is crossed once instead of three or four times.
For a user 280 ms from the origin, that takes TTFB from roughly 860 ms to roughly 320 ms with zero cache hits. Add HTTP/3 at the edge and the handshake shrinks further.
Question 3
Anycast or DNS-based steering: what is the difference, and how does it change failover?
DNS steering gives each PoP its own addresses and answers each resolver with a nearby PoP. It allows fine control but guesses from the resolver's location, and failover waits for cached DNS answers to expire.
Anycast announces the same addresses from every PoP and lets BGP routing pick the nearest one. DNS is the same for everyone, failover takes seconds when a PoP withdraws its route, and attack traffic spreads out, but network-nearest is not always the fastest PoP.
Question 4
When would you run logic in edge middleware, and when would you keep it at the origin?
At the edge: decisions made from the request alone, like redirects, locale choice, auth gates on a cookie or signed token, A/B buckets that pick between cached variants, and headers. They save a long trip and keep pages cacheable.
At the origin: anything that talks to a database or a slow API, because the edge is far from the data and each query becomes a long round trip. Edge runtimes also have CPU, memory, and API limits, and a bug there ships to every PoP at once.
Question 5
We are switching CDNs next week. What could go wrong with DNS, and how do you plan it?
The record's TTL decides how long resolvers keep sending users to the old CDN. Lower it to about 60 seconds at least one old TTL ahead, test the new CDN fully, switch, and keep the old one serving for days, because some resolvers and clients hold answers longer than told.
Also plan for a cold cache on the new CDN: enable shielding, warm the busiest URLs, and watch origin load. Raise the TTL again once stable.
References
- MDN: What is a domain name? A gentle start on how names and DNS fit together.
- RFC 2308: Negative Caching of DNS Queries How long resolvers remember that a name does not exist.
- RFC 7871: Client Subnet in DNS Queries The ECS extension that lets CDNs steer by the user's network.
- Cloudflare Learning: What is anycast? Anycast routing explained by a provider that is built on it.
- Cloudflare Workers: How Workers works Isolates, cold starts, and the edge runtime model.
- web.dev: Optimize Time to First Byte Where TTFB comes from and how CDNs and edge caching cut it.
- Fastly: Summary of June 8 outage A real CDN outage: one customer's valid configuration change set off a hidden software bug.
- Cloudflare: Details of the Cloudflare outage on July 2, 2019 How one regular expression in a firewall rule took a global network down for 27 minutes.
Read next
- From URL to pixelsEverything that happens between pressing Enter and seeing a page: DNS, TCP, TLS, the HTTP exchange, redirects, parsing, and subresources, with where the time goes on a real phone, so you know which part to fix when a page is slow.
- CDN cachingKeeping shared copies of your responses on servers near every user, so most requests never travel to your origin: the biggest lever for global speed and for surviving traffic spikes.
- HTTP cachingThe browser's built-in cache, steered by headers on each response, which lets a repeat visit skip the network entirely or ask only "has this changed?": the cheapest speed-up on the web.
- HTTP/1.1, HTTP/2, and HTTP/3The same requests carried three ways (one at a time per TCP connection, many at once on one TCP connection, or many at once on QUIC over UDP), which decides bundling, sprites, sharding, and how a lossy network feels.
- Server-side renderingThe server builds the full HTML for each request, so users see content before any JavaScript runs, then the browser hydrates it: faster first paint and better SEO, paid for with server work, a later first byte, and a second render in the browser.
- Core Web VitalsThree numbers, measured on real users, that say whether a page loads fast (LCP), reacts fast (INP), and stays still (CLS): what each one measures, what makes it bad, and how to fix it.