Courses / System Design Interview / Chapter 5
Module 2 · Building Blocks · Chapter 5 of 39
DNS: How a Name Becomes an Address
Builds on What System Design Is: From One Server to Millions, Back-of-the-Envelope Estimates, Abstractions That Hide the Network and Availability, Reliability, Scalability and Latency. Next up: Load Balancers.
Part 1 · Names and Addresses
Why names need a directory
Results for 30 lakh students go live at 10 am. The night before, the board's team moved results.example.in to new servers in a cloud region and updated its DNS record. At 10:02 the complaints begin: students in Lucknow and Patna get timeouts while their friends in Pune see their marks. The new servers are healthy and half idle. The old ones were switched off at midnight. The record still carried the one-day lifetime it had always had, so caches across the country kept handing out the old address. Nothing was broken except the team's picture of how DNS works.
Machines find each other by IP address: four numbers for IPv4, such as 203.0.113.20, or a longer IPv6 address such as 2001:db8::20. People and programs use names. The Domain Name System (DNS) is the directory that turns a name into an address, much as the contacts list on your phone turns a name into a number.
An address belongs to a machine, and it changes when you switch providers, add servers or fail over to another region. A name stays the same while the addresses behind it change. That is what the results team relied on, and why DNS is the first layer of indirection in almost every system you will design.
To keep up with every device on the internet, DNS is distributed (no server holds every name), delegated (each organisation runs its own names) and heavily cached. Here is what those ideas buy:
| What DNS must handle | How it copes |
|---|---|
| Billions of devices asking all day | Answers are cached at several levels, so the top of the tree sees a small share of lookups |
| Millions of domains, no central admin | Each zone is run by its owner and delegated from its parent |
| Answers in milliseconds | Most lookups end at a nearby cache |
| No downtime, ever | Every zone has several servers; the top levels use anycast |
Caching carries most of that load, and caching is also what caught out the results team.
A tree of zones
How is one directory split across thousands of organisations? As a tree. Read a domain name from right to left, the way you read a postal address from the country down to the house. The invisible dot at the end is the root. Next comes the top-level domain (TLD), such as .in or .com. Then the name an organisation registers, example.in, and then names it creates under it, such as results.example.in.
Each level delegates the level below it. The root does not know where results.example.in lives; it only knows which servers handle .in. The .in servers know only which servers handle example.in. Those, the authoritative name servers, hold the actual records. A zone is the part of the tree that one organisation manages. The table shows who runs each level and what it knows.
| Level | Example | Run by | Knows |
|---|---|---|---|
| Root | . | About a dozen independent organisations | Which servers handle each TLD |
| TLD | .in | The registry for that TLD | Which servers handle each registered domain |
| Authoritative | example.in | The domain owner or its DNS provider | The real records: addresses, mail servers, aliases |
Example.
Run byAbout a dozen independent organisations
KnowsWhich servers handle each TLD
Example.in
Run byThe registry for that TLD
KnowsWhich servers handle each registered domain
Exampleexample.in
Run byThe domain owner or its DNS provider
KnowsThe real records: addresses, mail servers, aliases
Each level knows only the next step down, so no server needs the whole directory, and each owner changes its own records without asking anyone.
There are 13 root server names, a.root-servers.net to m.root-servers.net, run by about 12 operators. Each name is served by many machines worldwide through anycast, covered later in this chapter: well over a thousand in total.
Someone has to walk this tree when a student's phone asks for results.example.in. The next page meets that walker.
Part 2 · How a Lookup Works
Resolvers do the walking
Your phone does not walk the tree itself, and that is the first reason DNS is fast. Its operating system has a small stub resolver that checks a local cache and sends anything it cannot answer to a recursive resolver, usually run by your internet provider, your employer or a public DNS service. The recursive resolver walks the tree on your behalf and caches everything it learns.
That splits queries into the two kinds compared below. A referral is a reply that says "I do not know, but these servers do".
| Recursive query | Iterative query | |
|---|---|---|
| Sent by | A phone or laptop, to its resolver | The resolver, to root, TLD and authoritative servers |
| What comes back | The final answer, or an error | The answer, or a referral one level down |
| Who does the walking | The resolver | The asker, following each referral |
Handing the walk to a shared resolver means a phone sends one question and waits for one answer, however deep the tree.
- 1Browser or app cachenames it looked up recently
- 2Operating systemthe hosts file and the system's own cache
- 3Recursive resolvera cache shared by everyone who uses it
- 4Root, then TLD, then authoritativeonly when every cache above has missed
The first place with a fresh answer wins, so most lookups stop early. The resolver's cache matters most because it is shared: on results morning, the first student on a large provider's resolver warms it for lakhs of others.
A lookup, step by step
Here is that walk in motion: a first lookup for results.example.in through a resolver with an empty cache, then a second lookup a minute later by another student on the same resolver.
Predict before you watch: with an empty cache, how many servers must the resolver ask? And when a second phone asks a minute later?
- Three: a root server, a .in server and the results site's name server.
- None. The answer is still in the resolver's cache, so it replies at once.
Watch for how many servers the first lookup touches, and how many the second does
Read it as steps
Results morning: two students on the same resolver look up the results site a minute apart.
The walk is paid once per resolver, not once per phone. With every cache empty it cost three round trips from the resolver plus the phone's own trip: often 50 to 150 ms in total. The second student paid only the trip to the resolver, a few milliseconds to a few tens.
In practice even a first lookup rarely visits the root: the referral to the .in servers has a TTL of about two days, so busy resolvers already hold it.
Queries travel over UDP port 53, one small packet each way, with TCP for large answers. DNS over TLS (port 853) and DNS over HTTPS (port 443) encrypt the hop from a device to its resolver, hiding which names you look up.
TTL: the freshness dial
The resolver in the scene kept the answer for 300 seconds because the record told it to. That number, the TTL (time to live), is the most important setting in DNS. Think of it as a best-before date stamped on every answer.
Every cache that stores an answer, whether resolver, operating system or browser, starts its own countdown from the moment it fetched it, reuses the answer until zero, then asks again. Each resolver fetched at a different moment, so the copies expire at different moments, and a change spreads across users gradually over one TTL instead of switching at once. In the terms of Abstractions That Hide the Network, DNS is eventually consistent.
The owner picks the TTL per record, trading freshness against load, speed and resilience:
| Short TTL (60 to 300 s) | Long TTL (hours to a day) | |
|---|---|---|
| Changes reach users | Within minutes | Only as copies expire, up to a day |
| Queries to your name servers | About resolvers ÷ TTL: 50,000 resolvers at 60 s is about 830 a second | 50,000 resolvers at 1 hour is about 14 a second |
| Cold lookups for users | More often, each 50 to 150 ms | Rare |
| If your DNS provider goes down | Copies run out within minutes | Most users keep working for hours |
| Good for | Records that may move: APIs, failover | Stable records: name servers, mail |
A short TTL buys agility; a long TTL buys speed and resilience, so set it per record by how likely that record is to move.
A lookup for a name that does not exist returns NXDOMAIN ("no such name"), and resolvers cache that "no" for a time set in the zone's SOA (start of authority) record. Create a record just after someone looked it up, and their resolver may keep saying "no" until that time passes, so create names before you announce them.
Moving a service without stranding users
Back to results night. The team changed the address behind results.example.in while the record still carried a one-day TTL, then switched off the old servers. Every resolver that had fetched the record in the previous 24 hours kept the old address for up to another day. Here is the same move done safely:
- 1Two days before: lower the TTL from 1 day to 300 swait one full old TTL; copies fetched earlier still carry 1 day
- 2Move day: start the new servers and test them by addressreal users still reach the old ones
- 3Switch the record to the new addressmost resolvers pick it up within 5 minutes
- 4Keep the old servers for a weekforward stray requests to the new servers and watch their logs
- 5Raise the TTL againback to an hour or more once the move is stable
The first wait is the one teams skip. Lowering the TTL changes only copies fetched after the change, so if you lower it on move day, resolvers holding yesterday's copy still trust it for up to a day. Lower the TTL at least one old TTL before the move.
Even then, a tail of traffic reaches the old address after the switch. It has three usual causes: resolvers that raise very short TTLs to a minimum of their own, apps and runtimes that keep an address for the life of the process, and connections opened before the switch, which never look the name up again. Old servers that forward requests turn that tail into a little extra latency instead of errors.
Raising the TTL at the end matters too. With a 60 s TTL, an outage at your DNS provider makes the site vanish for most users within a minute; with an hour, cached copies run out gradually over the next hour, which is often long enough for the provider to recover.
Part 3 · Records and Load Spreading
The record types you will meet
So far the results site has needed one kind of record: an address. A zone is a list of records, each with a name, a TTL, a type and a value, and six types cover most designs:
| Type | Maps | Example | Used for |
|---|---|---|---|
| A | Name → IPv4 address | results → 203.0.113.20 | Reaching a server |
| AAAA | Name → IPv6 address | results → 2001:db8::20 | The same, over IPv6 |
| CNAME | Name → another name | static → results.cdn.example | Aliases: handing a name to a CDN or a cloud load balancer |
| MX | Domain → mail servers, with priorities | example.in → 10 mail.example.in | Delivering email |
| NS | Zone → its name servers | example.in → ns1.example.in | Delegation down the tree |
| TXT | Name → free text | example.in → "v=spf1 mx -all" | Proving domain ownership, email anti-spoofing rules |
MapsName → IPv4 address
Exampleresults → 203.0.113.20
Used forReaching a server
MapsName → IPv6 address
Exampleresults → 2001:db8::20
Used forThe same, over IPv6
MapsName → another name
Examplestatic → results.cdn.example
Used forAliases: handing a name to a CDN or a cloud load balancer
MapsDomain → mail servers, with priorities
Exampleexample.in → 10 mail.example.in
Used forDelivering email
MapsZone → its name servers
Exampleexample.in → ns1.example.in
Used forDelegation down the tree
MapsName → free text
Exampleexample.in → "v=spf1 mx -all"
Used forProving domain ownership, email anti-spoofing rules
Most designs lean on three of these: A or AAAA to reach a server, CNAME to hand a name to a provider, and NS to say who answers for a zone.
; name TTL type value example.in. 86400 NS ns1.example.in. results.example.in. 300 A 203.0.113.20 static.example.in. 3600 CNAME results.cdn.example. example.in. 3600 MX 10 mail.example.in.
Part of a zone file. Each record has its own TTL: short on the one that may move, long on the name servers.
A CNAME makes one name an alias for another, and the resolver then looks up the target, usually from cache. A CNAME cannot sit at the top of a zone (example.in itself), because that name must also hold NS and SOA records, so DNS providers offer a flattened alias record for that case. An MX number is a preference: senders try the lowest first. Others you may meet: SRV (host and port for a service), PTR (address back to name) and CAA (which certificate authorities may issue for the domain).
Using DNS to spread load
A name server can give different answers to different askers, which makes DNS a cheap first layer of load spreading. The results site now runs in two regions, Mumbai and Hyderabad; which one should a student in Patna reach? As Back-of-the-Envelope Estimates showed, every 1,000 km of fibre adds at least 10 ms to each round trip, so nearness matters. These are the common ways to choose:
| Technique | How it works | Good for |
|---|---|---|
| Round robin | Several A records; the order rotates and most clients try the first | Spreading users over a few entry points |
| Weighted | Answers handed out in a set ratio, such as 90 to 10 | Moving traffic to a new region gradually |
| Geo-based | The answer depends on where the resolver is | Keeping Indian users in an Indian region |
| Latency-based | The region with the lowest measured latency from that network | Apps with users in several countries |
| Health-checked failover | Stop handing out a region that fails its health checks: small test requests sent every few seconds | Moving users away from a failed region |
All five decide once per lookup, and then the answer is cached, so DNS steers whole groups of users at a time, never single requests.
DNS also sees the resolver, not the user. A student in Patna on a public resolver whose nearest site is in another city gets the answer meant for that city, unless the resolver passes a hint about the user's network (EDNS Client Subnet), at some cost to privacy. The split is lumpy, too: one large resolver may serve lakhs of users from a single cached answer. And a plain name server cannot see how busy each server is.
So the usual pattern has two layers: DNS picks the region, and a load balancer inside it picks the server. The table's last row, health-checked failover, sounds instant. The next page times it.
Why DNS failover is slow
At 10:05 on results day, the Mumbai region fails. The DNS provider has been sending a health check to each region every 10 seconds. How long until students sent to Mumbai see their marks again?
Changing a DNS answer is like changing a phone number printed in thousands of diaries: you cannot edit the diaries, only wait for people to look the number up again. Four delays add up:
- Detection: 3 failed checks in a row, 10 s apart, takes about 30 s.
- Update: the provider pushes the new answer to all its name servers, in seconds to a minute.
- Cached answers: every resolver holding Mumbai keeps it until its TTL runs out, up to 60 s more with a 60 s TTL.
- The tail: clients that ignore TTLs, and connections that never re-resolve, keep calling Mumbai for minutes or hours.
With a 60 s TTL, most users move within about two minutes; with 300 s, within about six. Watch one student live through it:
Watch for how long the phone keeps calling Mumbai after Mumbai fails
Read it as steps
Results day, 10:05: the Mumbai region fails while a resolver still holds its address.
The name server switched within 30 seconds, yet the student kept failing until the resolver's copy expired, because a DNS change reaches a user only when their cached answer runs out. So each region must survive a single server failure on its own, behind a load balancer, and DNS failover is saved for losing a whole region.
Part 4 · DNS in Practice
Failures and attacks
Slow failover is DNS working as designed. DNS can also fail outright, and then every healthy server behind it becomes unreachable. As Availability, Reliability, Scalability and Latency showed, a component in series caps the whole system, and DNS sits in front of every new visit; caches only hide an outage until their copies expire. Four failures are worth designing for:
| Problem | What users see | Defences |
|---|---|---|
| Resolver outage | Nothing resolves for that resolver's users, though every site is up | A second resolver on devices; resolvers run as redundant clusters, often behind anycast |
| Name servers down or flooded | Your domain fades away as cached copies expire | Name servers on separate networks, often two DNS providers; anycast; longer TTLs on stable records; resolvers that serve stale answers meanwhile |
| Cache poisoning | A resolver caches a forged answer and sends users to an attacker | Random query ids and source ports; DNSSEC signatures; HTTPS certificates as a second check |
| Misconfiguration or a lapsed domain | A wrong record or an expired registration takes the site down | Reviewed changes, monitoring of key records, auto-renewal and a lock at the registrar (the company you bought the domain from) |
The second row is the one to plan for on results day, because it has happened at scale.
In 2016, a DDoS attack (a flood of traffic from many machines) on one DNS provider made many well-known websites unreachable for hours in parts of the world, though the sites themselves were running. The common lesson: serve important zones from two providers. Resolvers also retry another listed name server when one is silent, which is why every zone lists at least two.
Cache poisoning works because classic DNS runs over UDP and a resolver accepts the first reply that matches its question, so an attacker races the real server with forged replies. A random 16-bit query id alone is a 1-in-65,536 guess; randomising the source port as well makes it a guess among billions. DNSSEC goes further: records are signed, and a resolver checks the chain of signatures from the root down, so a forged record fails.
Anycast: one address, many places
The defences above keep pointing to one technique. With anycast, servers in many cities announce the same IP address to the internet's routers, and each router sends packets along its best path to the nearest announcing site. It works like a national helpline number that connects you to the nearest call centre: everyone dials the same number, and the network picks the place.
The announcements travel over BGP, the protocol networks use to tell each other which addresses they can reach. That one mechanism gives DNS four things:
- Lower latency: a nearby site answers each query.
- DDoS absorption: each site takes only its share of a flood, instead of one site taking all of it.
- Automatic failover: a failed site withdraws its announcement, and routers move its traffic elsewhere, usually within seconds to a few minutes.
- A good fit: a DNS query is one small UDP packet each way, so a route change between queries breaks nothing.
Anycast also solves a problem DNS cannot solve for itself. DNS cannot steer users away from its own dead servers, because that steering would need DNS; routing does it instead. This is how 13 root names are served by well over a thousand machines.
It has two limits. "Nearest" means nearest in routing terms, so a user in Chennai can land in Singapore if that path is shorter for their network. And long-lived connections are harder, because a route change mid-connection can send packets to a site that knows nothing about the connection. Large providers still use anycast for web traffic, with extra work at the edge, as Load Balancers and Content Delivery Networks describe.
Finding services inside your system
Names solve the same problem inside your own system. The results API calls a marks service whose instances change every few minutes as deploys, autoscaling and failures replace machines. Keeping each caller's list of healthy instances current is service discovery, and there are three common ways to do it:
| Approach | How a caller finds instances | Trade-off |
|---|---|---|
| Internal DNS | Looks up a name such as marks.internal; the platform updates the records as instances come and go, with TTLs of a few seconds | Works with every client, but inherits caching delays and clients that ignore TTLs |
| A registry | Instances register and send heartbeats; callers, or a proxy beside each caller, watch the list | Changes arrive within seconds; callers need a library or a proxy |
| A load balancer per service | Callers use one stable address; the balancer tracks healthy instances | Simple callers, but an extra hop and one more component to run |
Internal DNS is the easy default; a registry wins when instances change faster than DNS caches can follow.
Names you will hear: Kubernetes gives every service an internal DNS name; Consul is a registry with health checks and a DNS interface; etcd and ZooKeeper are coordination stores that registries are often built on, covered in Consensus, Leader Election and Coordination. DNS can also return ports, through SRV records.
Some runtimes resolve a name once and keep the address for the life of the process, whatever the TTL says; certain Java configurations are a well-known case. Pooled connections do the same, because an open connection never re-resolves. After a failover these clients keep calling the dead address, so make runtimes respect TTLs and recycle pooled connections every few minutes.
In the interview
DNS is usually the first arrow on the board, and you rarely design it, you use it, so these lines carry most of what you need.
- Say
- "The client resolves api.example.in, and a latency-based answer sends users in India to the Mumbai region instead of paying about 200 ms a round trip to a US region."
- Say
- "The API record has a 60 s TTL, so a regional failover reaches most users in about two minutes; stable records like NS keep a day to cut lookups."
- Say
- "DNS failover takes minutes plus a tail, so each region also survives a server failure on its own behind a load balancer."
- Avoid
- "If a server dies, DNS sends users elsewhere instantly." Cached copies keep pointing at it for up to a TTL, and some clients never re-resolve.
- Avoid
- "Set every TTL to 5 seconds." That is 60 times the queries of a 5-minute TTL and many more 50 to 150 ms cold lookups, and some resolvers raise it anyway.
Wrap-up
| Term | Meaning |
|---|---|
| Recursive resolver | Walks the tree for clients and caches what it learns |
| Authoritative name server | Holds a zone's actual records |
| Zone | The part of the name tree that one organisation manages |
| TTL | How long a cached answer may be reused |
| CNAME | An alias from one name to another name |
| Anycast | Many sites announce one address; routers pick the nearest |
| Service discovery | Keeping callers' lists of healthy instances current |
Next, Load Balancers covers the second layer: once DNS has picked a region, how a load balancer spreads requests over the healthy servers inside it and pulls a dead one out in seconds rather than minutes.
Part 5 · Check yourself
Quick check
Q1Why is publishing the results site's 10 app servers as 10 A records a poor replacement for a load balancer?
Think it through, then check.
- Cached copies keep sending students to a dead server until TTLs run out, and some clients never try the next address.
- The split follows resolvers, not students, and DNS cannot see load. DNS should pick the region; a load balancer picks the server.
Q2Two days after the move, with a 300 s TTL in place, about 2% of the results site's traffic still reaches the old address. What is likely causing it?
Think it through, then check.
- Clients that ignore the TTL: runtimes that cache lookups for the life of the process, pooled connections that never re-resolve, or a hard-coded address.
- Find them in the old servers' logs; until they are fixed, keep the old servers forwarding to the new ones.
Q3A phone in Patna is 20 ms from its resolver; the resolver is 30, 40 and 60 ms from a root server, the .in servers and the results site's name server (round trips). How long is a lookup with every cache empty, with the .in servers cached, and with the answer cached?
Think it through, then check.
- Empty: 20 + 30 + 40 + 60 = 150 ms. With the .in servers cached, the root trip drops out: 120 ms.
- With the answer cached: 20 ms, which is where busy resolvers keep most lookups.
Q4On results day, should the results API's record have a TTL of 30 s or 1 hour? State the trade-off.
Think it through, then check.
- 30 s: failover reaches students soon after detection, but name-server queries rise 120-fold, more lookups pay 50 to 150 ms, and a provider outage bites within a minute.
- 1 hour: fast lookups that ride out a provider outage, but a failed region strands some students for up to an hour.
- Losing a region hurts most on results day, so lean short, around 60 s, and keep NS and MX at a day.
Q5From Availability, Reliability, Scalability and Latency: the results site is 99.95% available and relies on one DNS provider at 99.99%. What does DNS do to the total, and what does a second, independent provider change?
Think it through, then check.
- In series: 0.9995 × 0.9999 ≈ 99.94%, about 50 more minutes of downtime a year.
- Two independent providers are both down with chance 0.0001², one in a hundred million, so the total returns to about 99.95%, if they share no network and serve the same records.
All chapters · Previous: Availability, Reliability, Scalability and Latency