System Design (High-Level Design) Module 19 – Building blocks: traffic, storage and messaging
Design a DNS-based global traffic manager
Design authoritative DNS that steers users to a nearby healthy region, with quorum health checks, validated snapshots and a failover time you can compute.
What you will learn
- Estimate the query load, health-check traffic and failover time of a global traffic manager
- Design authoritative DNS that steers users by latency, location, weights and health
- Decide region health from probes in several networks without false failovers or flapping
- Validate versioned snapshots so that no change can leave a name without answers
- Protect the answers when the health data or the control plane fails
Before you start
What you’ll learn · Before you start
What you will learn
- Estimate the query load, health-check traffic and failover time of a global traffic manager
- Design authoritative DNS that steers users by latency, location, weights and health
- Decide region health from probes in several networks without false failovers or flapping
- Validate versioned snapshots so that no change can leave a name without answers
- Protect the answers when the health data or the control plane fails
Before you start
On this page
When a region fails, its users keep reaching it until the DNS answers cached for them expire: up to 104 seconds in
the design below. A DNS-based global traffic manager is the authoritative name server: A DNS server that holds a zone's records and answers for them itself, without asking any other server. Steering policies such as GeoDNS and health-checked failover run here. More in “DNS, GeoDNS and anycast for system design” for names such as api.example.com: it answers each query with the address of a healthy region near
the user, so steering and failover happen in the answer itself.
It has four parts: anycast: Announcing the same IP address from several sites, so that Internet routing delivers each packet to the nearest announcement by its own measure. A failed site withdraws its route, and traffic moves to the others. More in “DNS, GeoDNS and anycast for system design” name servers that answer; a policy store with weights, location maps and latency maps; health checkers in several independent networks; and a pipeline that turns policy and health into versioned snapshots for every name server. The hard part is who may call a region down, and what the name servers answer when everything behind them fails.
Requirements and estimate: TTLs set the load and the failover time
A company serves its API and app from four regions, Mumbai, Singapore, Frankfurt and Virginia, to users on every continent. Today a regional outage needs an engineer to change DNS by hand, and the change reaches users only as their caches expire. Ask first:
| Question | Assumed here |
|---|---|
| How many names, regions and endpoints, and how many resolvers ask for them? | 40 names, 4 regions with 3 load-balancer addresses each, about 400,000 resolvers |
| Steer by location, by measured latency, by fixed shares, or to one primary region? | By latency, with weights for gradual moves |
| How soon must users leave a failed region, and what TTL can the clients live with? | Out of the answers within about two minutes |
| May every name be answered from every region, or must some stay in one country? | Payment names only from Indian regions |
| What should the name servers do when the health data or the configuration pipeline breaks? | Keep answering whatever fails |
Functional requirements: answer A and AAAA queries by each name’s policy; health checks for every endpoint; weights and drains; a default answer for networks the maps do not know; allowed regions per name; versioned changes with rollback. Non-functional requirements: an answer within a few milliseconds from a nearby site; no outage when any one site, region, prober network or the control plane: The part of a system that decides and distributes configuration, such as routes, certificates and policies, to the parts that carry the traffic, which together are called the data plane. More in “Service discovery, sidecars and service meshes” fails; and never an empty answer for a name that has a healthy region.
The first estimate, to change and run again:
# The first estimate for a DNS-based global traffic manager. Every input is an assumption, written down so that
# you can change it and run the script again.
RESOLVERS = 400_000 # recursive resolver addresses that ask for our names
NAMES_WARM = 10 # of our 40 names, how many an average resolver keeps in its cache
RECORD_TYPES = 2 # A and AAAA: dual-stack clients ask for both
TTL = 60 # seconds, for the records that fail over
RESPONSE_BYTES = 200 # one answer: two addresses plus the EDNS record
SITES, SERVERS_PER_SITE = 16, 4
FLOOD_FACTOR = 100 # spare capacity for floods, as a multiple of the legitimate rate
ENDPOINTS = 12 # 4 regions x 3 load-balancer addresses
CHECKERS = 24 # 8 networks x 3 probers
INTERVAL = 10 # seconds between probes from each prober
FAILURES = 3 # failed probes in a row before an endpoint counts as down
PROBE_TIMEOUT = 4 # seconds a prober waits before calling a probe failed
AGREE, PUSH = 5, 5 # seconds to combine the votes, and to reach every name server (p99)
queries = RESOLVERS * NAMES_WARM * RECORD_TYPES / TTL
servers = SITES * SERVERS_PER_SITE
print("DNS queries")
print(f" {RESOLVERS:,} resolvers x {NAMES_WARM} names x {RECORD_TYPES} record types / {TTL} s TTL "
f"= {queries:,.0f} queries a second")
print(f" answers out: {queries * RESPONSE_BYTES / 1e6:.1f} MB a second "
f"({queries * RESPONSE_BYTES * 8 / 1e6:.0f} Mbit/s)")
print(f" per name server ({SITES} sites x {SERVERS_PER_SITE}): {queries / servers:,.0f} a second; "
f"with {FLOOD_FACTOR}x flood headroom: {queries / servers * FLOOD_FACTOR:,.0f}")
print("Health checks")
print(f" {CHECKERS} probers x {ENDPOINTS} endpoints / {INTERVAL} s = {CHECKERS * ENDPOINTS / INTERVAL:.1f} probes "
f"a second; each endpoint sees {CHECKERS / INTERVAL:.1f} a second")
detect_best = (FAILURES - 1) * INTERVAL + PROBE_TIMEOUT
detect_worst = FAILURES * INTERVAL + PROBE_TIMEOUT
print("Failover time for a client that obeys the TTL")
print(f" notice: {FAILURES} failed probes {INTERVAL} s apart, plus a {PROBE_TIMEOUT} s timeout: "
f"{detect_best} to {detect_worst} s")
print(f" agree on the vote and push the new answers: {AGREE} s + {PUSH} s")
print(f" cached answers expire: up to {TTL} s")
print(f" worst case: {detect_worst + AGREE + PUSH + TTL} s; "
f"the TTL is {TTL / (detect_worst + AGREE + PUSH + TTL):.0%} of it") Output
DNS queries 400,000 resolvers x 10 names x 2 record types / 60 s TTL = 133,333 queries a second answers out: 26.7 MB a second (213 Mbit/s) per name server (16 sites x 4): 2,083 a second; with 100x flood headroom: 208,333 Health checks 24 probers x 12 endpoints / 10 s = 28.8 probes a second; each endpoint sees 2.4 a second Failover time for a client that obeys the TTL notice: 3 failed probes 10 s apart, plus a 4 s timeout: 24 to 34 s agree on the vote and push the new answers: 5 s + 5 s cached answers expire: up to 60 s worst case: 104 s; the TTL is 58% of it
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 gtm_estimate.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
The query rate is set by resolvers and TTLs, not by users: a recursive resolver: The DNS server that answers a device's question in full. It follows referrals from the root down to the servers authoritative for the name, and caches every answer for its TTL so the next user skips the walk. More in “DNS, GeoDNS and anycast for system design” that keeps a name warm asks once per TTL (DNS): Time to live: the number of seconds a resolver or a client may keep a DNS answer in its cache before it must ask again. A change reaches a user only once the cached copy's TTL has run out. More in “DNS, GeoDNS and anycast for system design”, however many people it serves. The failover budget: The time from a region's failure until the last client that obeys the TTL has moved away: noticing the failure, agreeing on it, pushing new answers to every name server, and waiting for the cached answers to expire. is mostly the TTL, which is why the TTL of a name that fails over is chosen together with its health checks.
Checkpoint
Check the estimate
The first design answers from a validated snapshot
The first design of the global traffic manager
Text description of the diagram
The diagram shows the first design from top to bottom.
- Users and their recursive resolvers ask for a name such as api.example.com, then connect to a region that the answer names.
- Anycast name servers in many sites answer each DNS query with addresses and a TTL. Each site answers from the last valid snapshot it holds.
- A snapshot builder gives every snapshot a version, validates it and pushes it to all sites.
- Its inputs are the policy store, which holds weights, the latency map, the regions each name may use and the default answers, and the health aggregator, which turns probe results into one verdict per endpoint by a quorum of networks.
- Health checkers in 8 independent networks send their probe results to the aggregator. A dashed arrow shows that they probe every endpoint of every region.
- The regions are Mumbai, Singapore, Frankfurt and Virginia, each with its load balancers.
Each part of the design has one job:
- Anycast name servers: the same addresses announced from every site, so a query reaches a nearby site and a failed site drops out of routing.
- Policy store: for each name, its regions, weights, latency and location maps, allowed regions and default.
- Health checkers: probers in several independent networks that test every endpoint on a schedule.
- Health aggregator: turns many probes into one verdict per endpoint by a vote across networks.
- Snapshot builder: joins policy and verdicts into one versioned snapshot of every answer, and validates it.
- Distribution: pushes each snapshot to every site, where it replaces the old one only after a local check.
- Last valid snapshot: what a name server keeps answering from when nothing newer and valid arrives.
Follow one Mumbai outage through these parts:
The drawing shows the whole scene; its 6 steps are listed below.
Every step as text
- Mumbai stops serving. Mumbai's load balancers stop answering at second 0. Resolvers that cached Mumbai's addresses keep handing them out, so their users keep sending requests to a region that cannot answer.
- Three failed probes. Each prober checks every endpoint every 10 seconds and waits 4 seconds before it calls a probe failed. Three failures in a row take 24 to 34 seconds, depending on where between two probes the outage began.
- The vote. The health aggregator turns the probes of many networks into one verdict per endpoint, by a vote across networks. The estimate gives it 5 seconds.
- A validated snapshot. The snapshot builder joins the new verdicts with each name's policy, validates the result and pushes it to every site, where it replaces the old snapshot after a local check. The estimate gives the push 5 seconds, for 99 % of the name servers.
- Caches expire. Name servers now answer without Mumbai, but a resolver that cached the old answer may keep it for the whole 60-second TTL. Nothing the traffic manager does can shorten that wait.
- The sum. 34 + 5 + 5 + 60 = 104 seconds until the last client that obeys the TTL has moved. The TTL is 58 % of that budget, which is why a name that fails over gets its TTL and its health checks chosen together.
The deep dives that decide whether the design works:
- How many networks must agree before a region counts as down, and when may it come back?
- How does one query become an answer: allowed regions, health, latency, weights and defaults?
- What must a snapshot satisfy before any name server uses it, and how is an old one kept from overwriting a new one?
- What do the name servers answer when the health data or the control plane stops?
- How long do users keep reaching a failed region, given TTLs and clients that ignore them?
- How do names that must stay in one country fail over?
An answer is judged on requirements and estimates, steering, health checking, the snapshot pipeline, behaviour under failure and operations.
Checkpoint
Check the first design
The API, and one snapshot that holds every answer Pro: opens with a Pro, Premium or Ultimate pass
In this part:
- Steering one query in five steps, never to an empty answer
- Health by a vote of prober networks, measured
- Why one network must never decide
- Hold-down: a sick region stays out
- Distrusting the probers themselves
- Snapshots that cannot erase a name: a race reproduced
- Static stability: answering while the control plane is down
- Real settings give failover times of 96 to 160 seconds
- At 10× the snapshot gives out first, at 100× health checking
- Five alternatives, and why each loses
- What each level is expected to cover
- A sample answer and a 45-minute self-mock
- Practise: write the failover rule
- Decide when a region is down, by quorum and hold-down
- Interview questions
- Why does a DNS traffic manager judge a region's health from probers in several independent networks rather than from one?
- Your traffic manager removed the Mumbai region from its DNS answers for 20 minutes, although Mumbai was serving normally. Users in India were sent to Singapore and saw about 80 ms more latency. The probers of one network had lost their route to Mumbai. Explain how this happened and redesign the health decision.
- During a routine configuration change, your traffic manager answered queries for api.example.com with no addresses for four minutes, and clients kept failing for minutes after the fix. Each plan in the change was valid on its own. Explain how valid plans can produce an empty answer, why the failures outlasted the fix, and what you add.
- Product wants users moved off a failed region within 30 seconds. Your health-checked records have a 300-second TTL, and checks run every 30 seconds with 3 failures needed. What do you change, what does each change cost, and what can DNS not deliver however you tune it?
- Key takeaways
3 diagrams · 3 runnable examples (JavaScript) · 1 exercise with sample tests · 3 interview answers · about 58 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.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
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).
Terms in this lesson
- failover budget
- The time from a region's failure until the last client that obeys the TTL has moved away: noticing the failure, agreeing on it, pushing new answers to every name server, and waiting for the cached answers to expire.
References
- Choosing a routing policy (Amazon Route 53 Developer Guide) (Amazon Web Services)
- How Amazon Route 53 determines whether a health check is healthy (Amazon Web Services)
- How Amazon Route 53 chooses records when health checking is configured (Amazon Web Services)
- Best practices for Amazon Route 53 DNS (Amazon Web Services)
- Azure Traffic Manager endpoint monitoring (Microsoft)
- Summary of the Amazon DynamoDB Service Disruption in the Northern Virginia (US-EAST-1) Region (Amazon Web Services)
- Static stability using Availability Zones (Amazon Builders' Library) (Amazon Web Services)
- RFC 1034: Domain Names, Concepts and Facilities (IETF)
- RFC 2308: Negative Caching of DNS Queries (DNS NCACHE) (IETF)
- RFC 4786: Operation of Anycast Services (IETF)
- RFC 7871: Client Subnet in DNS Queries (IETF)
- RFC 8767: Serving Stale Data to Improve DNS Resiliency (IETF)
- Storage of Payment System Data (Reserve Bank of India)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress