Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

System Design (High-Level Design)  Module 19 – Building blocks: traffic, storage and messaging

Design a content delivery network

Design a CDN from requirements and estimates to points of presence, cache tiers, request collapsing, purges that reach every PoP and origin protection.

  • Advanced
  • 25 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free intro, Pro: 5 of 25 minutes free
Free: Requirements and estimate: the busiest PoP needs 16 servers. With a pass: the other 14 sections and 3 interview answers, about 20 minutes.

What you will learn

  • Estimate a CDN's egress, servers per point of presence and origin load from its requirements
  • Design points of presence, request routing and a cache hierarchy in front of an origin
  • Measure what owner servers, cache tiers and request collapsing do to hit ratios and origin load
  • Design purges that reach every point of presence quickly and safely, including unreachable ones
  • Plan certificates, configuration, failure drills and growth to ten times the traffic

Before you start

What you’ll learn · Before you start

What you will learn

  • Estimate a CDN's egress, servers per point of presence and origin load from its requirements
  • Design points of presence, request routing and a cache hierarchy in front of an origin
  • Measure what owner servers, cache tiers and request collapsing do to hit ratios and origin load
  • Design purges that reach every point of presence quickly and safely, including unreachable ones
  • Plan certificates, configuration, failure drills and growth to ten times the traffic

Before you start

On this page

At 3 million requests a second, 4.8 Tbit/s, a site’s files cannot all come from its own servers. A content delivery network (CDN) answers them from caching servers in many cities, called point of presence (PoP): One of a content delivery network's sites: a group of caching servers in a city close to users, which answers their requests from its caches and goes to the origin only on a miss. (PoPs), and goes to the site’s own servers, the origin, only on a miss.

Designing one means five decisions. Routing sends each user to a nearby PoP, by anycast or by DNS steering. A PoP of many servers must act as one cache, not many small ones. Tiers above the PoPs, a regional tier and a shield, catch misses before they reach the origin. Request collapsing turns many simultaneous misses for one object into a single fetch. And a change at the origin must reach every PoP, through purges or through new addresses.

Requirements and estimate: the busiest PoP needs 16 servers

Ask first what is served (files, images, video segments, cacheable API answers), for how many customer domains, how fast a purge must work and where the users are. This design takes these answers:

  • Functional: serve cached GET and HEAD responses for many customer domains, each with its own certificate, cache rules and origin; follow HTTP caching (RFC 9111); purge by URL and by tag; deliver each customer’s logs.
  • Non-functional: 3 million requests a second at peak, 200 KB per response on average; 95 % answered by the PoP; a purge applied at 99 % of PoPs within 2 seconds; keep serving when a PoP or the origin fails.
Quantity Working Result
Egress 3 million requests a second × 200 KB 600 GB/s, 4.8 Tbit/s
Busiest PoP 5 % of the traffic 150,000 requests a second, 240 Gbit/s
Its servers 25 Gbit/s cards run at 60 % 16 servers
PoP misses 5 % of 3 million 150,000 a second
Origin requests a shield answers 80 % of the misses 30,000 a second

The same estimate as a program, to change and run again:

Egress, servers per PoP and origin load Python · plan/cdn_estimate.py
# The first estimate for a CDN. Every input is an assumption, written down so that you can change it and run the
# script again.
import math

PEAK = 3_000_000  # requests a second at peak, every PoP together
RESPONSE_BYTES = 200_000  # average response, 200 KB
POPS = 60
BUSIEST_PERCENT = 5  # the busiest PoP's share of the traffic
CARD_GBIT = 25  # network card of one cache server
CARD_PERCENT = 60  # run the cards at 60 % at peak
POP_HIT_PERCENT = 95  # requests the PoPs answer themselves
SHIELD_HIT_PERCENT = 80  # PoP misses that the shield answers

gbit = PEAK * RESPONSE_BYTES * 8 / 1e9
print("Egress")
print(f"  {PEAK:,} requests a second x 200 KB = {gbit / 8:,.0f} GB/s, {gbit / 1000:.1f} Tbit/s")
print(f"  over {POPS} PoPs: {gbit / POPS:.0f} Gbit/s each on average, but traffic is never even")

busiest = PEAK * BUSIEST_PERCENT // 100
busiest_gbit = busiest * RESPONSE_BYTES * 8 / 1e9
per_server = CARD_GBIT * CARD_PERCENT / 100
servers = math.ceil(busiest_gbit / per_server)
print("The busiest PoP")
print(f"  {BUSIEST_PERCENT} % of the traffic: {busiest:,} requests a second, {busiest_gbit:.0f} Gbit/s")
print(f"  {CARD_GBIT} Gbit/s cards at {CARD_PERCENT} %: {busiest_gbit:.0f} / {per_server:.0f} = {servers} servers")

misses = PEAK * (100 - POP_HIT_PERCENT) // 100
origin = misses * (100 - SHIELD_HIT_PERCENT) // 100
print("The origin")
print(f"  PoP misses: {100 - POP_HIT_PERCENT} % of {PEAK:,} = {misses:,} a second")
print(f"  past a shield that answers {SHIELD_HIT_PERCENT} % of them: {origin:,} a second")
print(f"  without the shield it would see all {misses:,}")

Output

Egress
  3,000,000 requests a second x 200 KB = 600 GB/s, 4.8 Tbit/s
  over 60 PoPs: 80 Gbit/s each on average, but traffic is never even
The busiest PoP
  5 % of the traffic: 150,000 requests a second, 240 Gbit/s
  25 Gbit/s cards at 60 %: 240 / 15 = 16 servers
The origin
  PoP misses: 5 % of 3,000,000 = 150,000 a second
  past a shield that answers 80 % of them: 30,000 a second
  without the shield it would see all 150,000

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 cdn_estimate.py

Checkpoint

Check the estimate

  1. Question 1 of 3 The CDN serves 3 million requests a second at peak, 200 KB per response on average. How many terabits a second leave its PoPs?

    Type a number.

    A hint

    Multiply requests by bytes, then turn bytes into bits.

    Show the answer: Question 1 of 3

    Answer: 4.8 Tbit/s (anything from 4.32 to 5.28 counts)

    3,000,000 × 200 KB = 600 GB a second, and × 8 = 4,800 Gbit/s, which is 4.8 Tbit/s. Spread over 60 PoPs that is 80 Gbit/s on average, but traffic is never spread evenly, so the busiest PoP sets the size of a PoP.

  2. Question 2 of 3 The busiest PoP carries 5 % of those 3 million requests a second. Its servers have 25 Gbit/s network cards, run at 60 % at peak. How many servers does it need?

    Type a number.

    A hint

    Work out the PoP's Gbit/s first, then what one server carries at 60 % of its card.

    Show the answer: Question 2 of 3

    Answer: 16 servers (anything from 14.4 to 17.6 counts)

    5 % of 3,000,000 is 150,000 requests a second, × 200 KB = 30 GB/s = 240 Gbit/s. At 60 % of 25 Gbit/s each server carries 15 Gbit/s, so 240 ÷ 15 = 16 servers, before any spare for a failed server or a neighbour's traffic.

  3. Question 3 of 3 PoPs answer 95 % of the 3 million requests a second. Their misses go to a shield that answers 80 % of what reaches it. How many requests a second reach the origin?

    Type a number.

    Show the answer: Question 3 of 3

    Answer: 30000 requests a second (anything from 27000 to 33000 counts)

    3,000,000 × 5 % = 150,000 misses a second leave the PoPs, and 20 % of them, 30,000 a second, miss at the shield too. Without the shield the origin would see all 150,000.

The first design: one cache per PoP, and two tiers above it

CDN design: users reach a nearby PoP of 16 cache servers; misses go to a regional tier, then a shield, then the origin.UsersPoint of presence (one of 60)Regional tierone per regionShieldnext to the originCustomer originControl planeconfiguration, purges, certificates, logsLayer-4 load balancersspread connections16 cache serversTLS; the object's owner serves it1. anycast or DNS steering2. miss3. miss4. miss, collapsedpush and collect

The first complete design: a PoP, two tiers above it, and the control plane

Text description of the diagram

Users (1) reach a nearby point of presence, one of 60, by anycast or by DNS steering.

Inside the point of presence, layer-4 load balancers spread connections over 16 cache servers. The server that receives a request terminates TLS and has the request served by the object's owner, the one server in the point of presence that stores that object.

On a miss (2), the request goes to the regional tier of its region. On a miss there (3), it goes to the shield next to the origin, and only on a miss at the shield (4) to the customer's origin. Concurrent misses for the same object are collapsed into one fetch.

A control plane pushes configuration, purges and certificates to every point of presence and collects their logs.

Along the request path: anycast or DNS steering brings a user to a nearby PoP, where layer-4 load balancers spread connections over its 16 cache servers. The server that terminates TLS builds the cache key: The value a cache files a stored response under: at least the method and the full URL, plus the request headers the response names in Vary. Requests with the same key get the same stored response. More in “CDNs and edge caching” and has the object’s owner in the PoP serve it. A miss goes to the regional tier, then to a shield next to the origin, and only then to the origin, with concurrent misses for one object collapsed into one fetch. A control plane pushes configuration, purges and certificates to every PoP and collects their logs. Follow one request that misses everywhere:

Interactive · stage by stage One request that misses at every tier Step through one request from a user to the origin and back, and see what each tier does with it.
One request that misses at every tier, step 7 of 7. Showing The nearest PoP, The object's owner (one fetch for all misses), Regional tier (copy stored on the way), Shield by the origin (copy stored on the way), The origin.The nearest PoPanycast or DNS steeringThe object's ownerone fetch for all missesRegional tiercopy stored on the wayShield by the origincopy stored on the wayThe origin

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. To a nearby PoP. A user asks for a product image. Anycast or DNS steering brings the request to a nearby point of presence, one of 60.
  2. The server that owns it. A layer-4 load balancer hands the connection to one of the 16 cache servers, which ends TLS, builds the cache key and asks the key's owner, the one server of the PoP that stores this object.
  3. A miss at the PoP. The owner has no fresh copy. The PoPs answer 95 % of requests themselves, and this one is among the 5 % that go on, 150,000 a second across the CDN.
  4. The regional tier. The miss goes to the regional tier of the PoP's region, which serves all the PoPs there. It has no copy either.
  5. The shield. Next comes the shield next to the origin. In the estimate a shield answers 80 % of the PoPs' misses; this request is one of the rest.
  6. The origin answers. Only now does the request reach the origin, which sees 30,000 requests a second instead of 150,000. On the way back each tier can keep a copy for the next user.
  7. Misses collapsed. Other users who missed the same object at the same owner while this fetch was in flight did not start fetches of their own. They waited for this one, so concurrent misses cost the origin a single fetch.

The deep dives this design must answer:

  • Anycast or DNS steering: anycast announces one address from every PoP; DNS steering answers each resolver with a chosen PoP.
  • Owners inside a PoP: hashing each cache key to one server turns 16 small caches into one large one.
  • Tiered caching: a regional tier and a shield answer misses before the origin sees them.
  • Request collapsing: concurrent misses for one object wait for a single fetch.
  • Stale-while-revalidate and stale-if-error: a cache serves a stale copy while it refreshes, or while the origin fails.
  • Purge fan-out: every PoP must apply each purge and confirm it, even one that was unreachable.
  • Surrogate keys: tags on cached responses let one purge remove every object that carries the tag.
  • Certificate automation: ACME issues and renews the certificates of every customer domain.
  • Cache poisoning: a harmful response stored in a shared cache reaches every user of that cache.

Two or three of these usually fill the second half of a round. The rubric looks at the questions asked, the numbers, the request path, the chosen deep dives, the failures handled and the plan for growth.

Checkpoint

Check the first design

  1. Question 1 of 3 In the first design, which of a PoP's 16 cache servers stores a given object?

    Choose one answer.

    Show the answer: Question 1 of 3

    Answer: Its owner, the one server that the hash of the object's cache key picks

    The server that terminates TLS builds the cache key, and the key's owner serves the object. Hashing each key to one server makes the PoP's 16 caches act as one.

  2. Question 2 of 3 A request misses at its PoP. Where does it go next, in the first design?

    Choose one answer.

    Show the answer: Question 2 of 3

    Answer: To the regional tier, then to the shield next to the origin, and only then to the origin

    A miss climbs from the PoP to its regional tier, then to the shield by the origin. In the estimate, a shield that answers 80 % of the PoPs' misses leaves 30,000 of 150,000 a second for the origin.

  3. Question 3 of 3 Two hundred users ask the same cache server for one object within a few milliseconds of its copy expiring. What does the first design send to the next tier?

    Choose one answer.

    Show the answer: Question 3 of 3

    Answer: One fetch, which every one of those requests waits for

    The request path collapses concurrent misses for one object into a single fetch, so a popular object's expiry costs the next tier one request instead of one per user.

Owners by hashing turn sixteen caches into one Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • A regional tier and a shield cut origin requests 2.3 times
  • Collapsing turns 625 fetches into one, and stale copies remove the wait
  • A purge counts only when every PoP has applied it
  • Anycast or DNS steering, and the headroom to drain a PoP
  • Certificates renew 0.75 times a second, and logs reach 104 TB a day
  • Failure drills: seven ways the design is tested
  • At 10× the ports give out first, at 100× the control plane
  • What each level is expected to cover
  • A sample answer in ten minutes
  • A 45-minute self-mock
  • Practise: collapse the fetches
    • Count origin fetches with request collapsing
  • Interview questions
    • What is an origin shield in a CDN, and what does it cost?
    • A legal notice requires an image to be gone from every PoP within 10 minutes. The purge reached 59 of your 60 PoPs in a second, but one PoP has been unreachable from the control plane for 20 minutes while still serving users. What do you do now, and what would you build so this is never a scramble?
    • A game publisher releases a 2 GB patch at a fixed time. Within a minute of the release its origin falls over, although your CDN reports a 97 % hit ratio for the customer. Explain what happened and how the CDN should protect the origin next time.
    • Users of one PoP report that a customer's homepage loads scripts from a domain nobody recognises. The origin builds absolute script addresses from the X-Forwarded-Host request header. Explain how that page got into the cache and how you fix it in the CDN and at the origin.
  • Key takeaways

2 diagrams · 4 runnable examples (JavaScript, Python) · 1 exercise with sample tests · 3 interview answers · about 44 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Read a complete sample first: Design a unique ID generator

Terms in this lesson

point of presence (PoP)
One of a content delivery network's sites: a group of caching servers in a city close to users, which answers their requests from its caches and goes to the origin only on a miss.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.