Build a CDN (13 scenes)
Scene 01 · Without a CDN, every user crosses the planet
One origin, three continents, and the cost: every user pays full cross-ocean RTT and origin RPS scales with your user count.
Previously

The map ended at a single origin reached by a long trip; before we add any caches back, feel exactly how expensive that trip is when every user in the world has to make it.

Scene 01
Without a CDN, every user crosses the planet
Diagram
A world map with user pins in distant regions and one server box in us-east. Each in-flight request draws an arc from a user across the ocean and back, with a badge showing the round-trip time. Above the server, a gauge tracks **ORIGIN RPS** — requests per second arriving at the box. Along the bottom, per-region p50 strips show the typical wait users in that region see. Two terms anchor the picture: **origin** — the single authoritative server that owns the canonical copy of your content. **RTT** — round-trip time, how long it takes for a packet to reach a server and a reply to come back.
users 3 · in-flight 3WITHOUT A CDNRTT 245 msRTT 95 msRTT 130 msORIGINus-eastORIGIN RPS6 / 8001São Paulo1Frankfurt1SydneyPER-REGION p50 LATENCY (more users does NOT shrink these bars)São Paulo1u130 msp50ocean-boundFrankfurt1u95 msp50near originus-east0u8 msp50near originMumbai0u220 msp50ocean-boundSydney1u245 msp50ocean-boundevery user is one ocean away from the only copy of the content
One origin in us-east. Every user — wherever they live — pays the full ocean-crossing round trip to reach it. That round trip is the RTT.
Three users — one in São Paulo, one in Frankfurt, one in Sydney — all firing requests at the same single server in us-east. Watch the request arcs visibly cross oceans and the time it takes for the request to travel there and the reply to come back, which we'll call the round-trip time (RTT), settle into the 100-250 ms range. The server above the map is the one authoritative source for every request; its load gauge climbs as more requests arrive.
Implementation
Client.request
what every browser does when there is no cache in front
1def request(url):
2 # DNS resolves to the one origin in us-east
3 origin_ip = dns.resolve(origin_host)
4
5 # one TCP+TLS handshake, then the GET — each
6 # leg of the trip costs (distance / c) milliseconds
7 conn = tcp.connect(origin_ip) # 1 RTT
8 conn.send(http.get(url)) # 1 RTT
9 response = conn.recv() # waits here
10
11 return response # total wait ~= rtt_to(us-east)
Origin.serve
the one box every request in the world ends up at
1rps_counter = 0 # what the gauge above the box reads
2
3def serve_forever():
4 while True:
5 conn = listener.accept() # next user, anywhere
6 rps_counter += 1 # +1 per arriving request
7
8 req = conn.recv()
9 body = storage.read(req.path) # no cache layer
10 conn.send(http.ok(body))
11 conn.close()
rtt_to(region)
what the per-region latency strips are actually computing
1# Set by physics, not by how busy the origin is.
2# Cross-ocean ~150 ms, cross-continent ~80 ms,
3# nearby ~30 ms (HPBN, ch. 1).
4def rtt_to(user_region):
5 distance_km = great_circle(user_region, ORIGIN)
6 propagation = distance_km / SPEED_OF_LIGHT_IN_FIBER
7 return 2 * propagation # there AND back
8
9# Notice: user_count does not appear anywhere here.
10# Adding users cannot shrink any one user's trip.