Vibe Engines
YouTube
System Design

Design DNS

Step 1 / 9

Learn system design by building the Domain Name System step by step.

The numbers to beatroot→ TLDTLD→ authoritativeauth→ the record

The whole design, in writing

Learn system design by building the Domain Name System step by step. An interactive guide covering why one central name→IP table can't work, a delegated hierarchy of root / TLD / authoritative servers, recursive resolution, caching with TTL, replication and anycast for availability, GeoDNS and latency-based routing, and the unhappy paths (propagation, negative caching, DDoS, DNSSEC).

Every step of the build above, written out: the problem each piece solves, the option that was taken and the ones that were not, the numbers, and how it fails in production.

The big idea

What does DNS do?

Computers talk over IP addresses (142.250.72.14); humans remember names (google.com). Something has to translate names to addresses — billions of times a second, for every domain on Earth, with no central owner and no downtime. That's a deceptively hard distributed-systems problem.

Clientwants an IP
New in this step: Client.

DNS is the internet's phone book: give it a name, it returns an address. The trick is doing it at planetary scale. There's no single table — the namespace is split into a hierarchy that's delegated to independent owners, walked by resolvers, and made fast by aggressive caching.

What the new pieces do

Clientclient
A browser (its OS stub resolver) that has a name like vibeengines.com and needs the IP address to connect to.

Step 1 · The naive table

One giant lookup table?

The simplest design: one central server holding a table of every name → IP mapping on the internet. Every device queries it. Why is that a non-starter?

Clientwants an IP
The system as it stands at this step.

One central name→IP table for the whole internet. What breaks first?

  1. Building it once isn't the problem. The problems are load, failure, and ownership: one server can't take the planet's query rate, is a single point of failure, and no single entity can be trusted to own every name.

  2. Address exhaustion is a separate concern (IPv6). The naive table fails for reasons of scale, availability and control, not address space.

  3. One table means one bottleneck, one thing to DDoS into oblivion, and one owner deciding every domain on Earth. DNS solves all three by splitting and delegating the namespace.

Three fatal problems: load (no machine serves the whole internet's queries), availability (one table is one thing to kill), and control (no single entity should own every name). The answer to all three is the same: don't centralize the table — split and delegate it.

Why this piece earns its place

The obvious rescue for the central table is to shard it — a hundred machines behind a load balancer, still one operator. That fixes exactly one of the three problems. Load spreads, but the shard map is a global index somebody has to publish and keep consistent, and it is still one organisation deciding which names exist and which resolve. Delegation is different in kind: the name’s own dotted structure is the shard map, so there is nothing to publish, and each slice is run by whoever owns it. What that buys costs something honest, and I would say it out loud — correctness now depends on thousands of independent operators nobody controls, and a zone whose owner runs it badly is badly run for everyone who visits it. The system trades one failure it cannot survive for many small ones it can: a bad zone takes out one name, not the internet. That is the whole argument for hierarchy over a bigger box.

Step 2 · Someone to do the walking

The recursive resolver

If the answer isn't in one place, a client would have to chase it across many servers. You don't want every phone and laptop implementing that whole dance. Who does the legwork?

Clientwants an IPRecursive Resolvere.g. 8.8.8.8
New in this step: Recursive Resolver.

If no single server has the answer, who does the multi-step lookup for the client?

  1. Making every stub device chase the hierarchy is wasteful and un-cacheable across users. You want a shared component that does the walk once and caches for everyone.

  2. The OS stub resolver hands the whole question to a recursive resolver (your ISP's, or 8.8.8.8). It does the root→TLD→authoritative walk and returns just the answer — and caches it to help the next user.

  3. The root doesn't hold final IPs (it would be the central table again) — it only points to TLDs. A resolver is needed to follow those pointers down the tree.

Introduce the recursive resolver (your ISP's, or a public one like 8.8.8.8). The client's tiny stub resolver asks it one question — "what's the IP for vibeengines.com?" — and the resolver does all the walking, returning just the final answer. It also caches, so it can answer the next person instantly.

Why this piece earns its place

Handing the walk to a shared resolver concentrates something. Every client behind it inherits its outages, its policy and its view of the namespace, and it sees every name those clients look up — which makes it the natural place to log, filter or redirect. One bad entry in its memory is wrong for everybody behind it rather than for one laptop. So the resolver is the component here most worth treating as replaceable: stubs are configured with more than one, they fall back when the first stops answering, and on a hostile network the resolver handed out by DHCP is exactly the thing quietly substituted. The design does not remove that risk, it moves it somewhere a user can choose. The reason it is still the right call is that the alternative spreads the same trust across every device while sharing nothing — each one walking the tree itself multiplies upstream load by the number of devices and reuses not a single answer.

What the new pieces do

Recursive Resolverresolver
The workhorse (your ISP's or 8.8.8.8). Does the legwork: walks the hierarchy on your behalf and returns the final answer.

Step 3 · Split the namespace

A delegated hierarchy

The resolver needs to find the answer without any one server knowing everything. How do you organize billions of names so the lookup is a short, delegated walk instead of one impossible table?

Recursive Resolvere.g. 8.8.8.8Root Servers. → TLDTLD Servers.com → zoneAuthoritative NSzone → IP
New in this step: Root Servers, TLD Servers, Authoritative NS.

How is the name space organized so no server holds everything?

  1. An alphabetical shard has no natural owner per name and still needs a global index to find the right shard. DNS uses the name's own structure — its dotted parts — to delegate ownership.

  2. Read a name right-to-left: root knows who runs .com; the .com TLD knows who runs vibeengines.com; that authoritative nameserver holds the actual records. Each level owns and delegates its slice.

  3. A central directory of locations is just the central table again, one indirection removed. The hierarchy needs no global index — the name itself tells you where to go next.

Organize names as a tree, read right-to-left, with each level delegating to the next. The root knows which servers run each TLD; the TLD servers (.com) know which authoritative nameserver owns vibeengines.com; that authoritative server holds the real records. No server knows everything — each just points one step down.

Why this piece earns its place

This step bakes in an assumption worth naming: a zone is only as reachable as everything above it, and as everything its nameservers themselves depend on. Delegation gives each level independence in what it publishes, not independence in failure. If the parent’s delegation is wrong or withdrawn, the zone answers perfectly and nobody can find it, because resolvers never arrive. The same is true one step sideways — nameserver names live in some zone too, and if that zone is a domain someone forgot to renew, the delegation points at nothing, or at whoever registers it next. The practical rule that falls out is to verify the delegation from the outside rather than trusting your own servers’ view of it, and to keep nameserver names in a zone you would notice expiring. Ownership in DNS is delegated downward, which also means it can be revoked or fumbled upward, and no amount of redundancy inside a zone defends against that.

  • root→ TLD
  • TLD→ authoritative
  • auth→ the record

What the new pieces do

Root Serversdata
The top of the tree. Doesn't know vibeengines.com, but knows which servers run .com. 13 anycast identities worldwide.
TLD Serversdata
The .com registry servers. Don't hold the final IP, but know which authoritative nameserver owns vibeengines.com.
Authoritative NSdata
The nameserver that actually owns the zone. It holds the real records (A/AAAA/CNAME) and gives the final answer.

Back of the envelope

root delegates TLDs
knows who runs .com/.org/…
TLD delegates zones
knows vibeengines.com's NS
authoritative holds records
A / AAAA / CNAME / MX

Step 4 · The walk

Recursive resolution, step by step

Put it together: the resolver has a name and knows the tree exists. Trace exactly how it turns vibeengines.com into an IP starting from knowing nothing but the root.

ClientRecursive ResolverRoot ServersTLD ServersAuthoritative NS
The system as it stands at this step. · swipe to pan the diagram

The resolver walks down: ask a root server → it refers you to the .com TLD servers. Ask a TLD server → it refers you to vibeengines.com's authoritative nameserver. Ask the authoritative server → it returns the A record (the IP). Three referrals, one answer. The resolver hands it back to the client — and remembers it.

Why this piece earns its place

Three hops is the best case, and it is the parent’s glue that keeps it there. A delegation names nameservers, it does not give their addresses, so if a zone’s nameservers are named inside the zone they serve, the resolver needs the address of a server it can only learn by asking that server — the loop glue records in the parent exist to break. Name them out of zone instead and the walk quietly grows an extra resolution before it can even ask the real question. The other thing worth saying is what a cold walk actually costs. It is not three cheap hops, it is three chances to land on a slow or silent server, and the user experiences the total as a page that will not start. That is why a resolver keeps a round-trip estimate per nameserver and prefers the fastest one that has been answering, and why every level insists on more than one address to try.

  • 3 hopsroot → TLD → auth
  • root hintsknown in advance
  • A recordthe final IP

Step 5 · Why it feels instant

Caching with TTL

A three-server walk for every single lookup would be slow, and would crush the root and TLD servers under the whole internet's traffic. Yet DNS feels instant. What makes it fast and spares the upstream servers?

Recursive Resolvere.g. 8.8.8.8Resolver Cacheanswers + TTL
New in this step: Resolver Cache.

A full walk every lookup would be slow and crush the root/TLDs. What saves it?

  1. No server is fast enough to answer the whole internet's queries directly — that's the central-table trap again. The load must be kept away from the root entirely.

  2. Names are looked up constantly across billions of users. What makes it cheap isn't rarity — it's that answers are reused via caching for a bounded time.

  3. Each record carries a TTL set by its owner. The resolver caches the answer for that long, so the overwhelming majority of queries are served from cache and never touch root/TLD/authoritative servers at all.

Caching with a TTL. Every record carries a Time To Live set by its owner (e.g. 300s or a day). The resolver caches each answer for that long, so almost every lookup is served straight from the resolver's memory — never touching the hierarchy. Caching is what makes DNS fast and what keeps the root and TLD servers from being overwhelmed.

Why this piece earns its place

Two TTLs decide how fast a change lands, and only one of them is yours. Records inside the zone carry a TTL their owner sets; the delegation pointing at your nameservers carries one the parent sets, and it is usually far longer — so moving a name to a new address is quick, while moving it to new nameservers is not. Setting the record TTL is a real dial with a cost in both directions. Long means fewer walks, faster answers, and the part people forget: an authoritative outage nobody notices, because cached copies keep resolving for as long as it lasts. Short means you can move quickly, but every expiry puts the full walk back in a user’s request path and makes your nameservers’ availability directly visible to them. So the usual shape is long by default, lowered deliberately ahead of a planned change and raised again afterwards. The exception is a name whose failover is automatic rather than planned: nobody gets to pre-lower a TTL for an outage they did not schedule, so there the short TTL is the mechanism and you pay its cost permanently.

  • ~90%+served from cache
  • TTLowner-set freshness
  • 0 hopson a cache hit

What the new pieces do

Resolver Cachecache
Remembers recent answers until their TTL expires. Most lookups are served straight from here — the reason DNS feels instant.

Step 6 · Never go dark

Replication & anycast

The root, the TLDs and each zone's authoritative server are now critical infrastructure. A single machine for any of them would be a global outage waiting to happen — and an irresistible DDoS target. How do you make them unkillable?

ClientRecursive ResolverResolver CacheRoot ServersTLD ServersAuthoritative NS
The system as it stands at this step. · swipe to pan the diagram

The root/TLD/authoritative servers are critical. How do you make them survive failure and attack?

  1. One box, however powerful, is still one target and one failure. DNS availability comes from many redundant servers answering as one, not a single fortress.

  2. Every zone runs multiple authoritative servers; the 13 root "identities" are each anycast to hundreds of physical servers worldwide. Many machines share one address, so load spreads and a dead one is simply routed around.

  3. Caching reduces load but records still expire and new names still need the hierarchy — the servers must be reachable. Availability of the servers themselves requires replication + anycast.

Replicate everything and front it with anycast. Every zone must run multiple authoritative nameservers. The 13 root server identities are each anycast to hundreds of physical machines around the globe — one IP, served from the nearest healthy instance. Load spreads, latency drops, and a dead server (or a DDoS on one location) is just routed around.

Why this piece earns its place

Anycast moves the failure domain into routing, and routing announces reachability, not health. A node that is up but answering badly — a bad config push, a full disk, a process that accepts queries and never replies — keeps attracting everything routed to it, and it is a black hole for precisely the users nearest to it while the global picture still looks fine. So the health check has to control the announcement: a node failing its own check withdraws its route and lets the network deliver those queries elsewhere. That is the mechanism that turns losing a node into a non-event; without it, anycast just spreads a broken answer efficiently. The second thing this step assumes is that the redundancy is real. Two nameservers are two failure domains only if they are genuinely separate — different networks, different providers, ideally different software — because two names on one provider share its outages, its routing and its control plane, and count as one.

  • 13 → 100sroot identities → machines
  • ≥2authoritative NS per zone
  • anycastnearest healthy answers

Step 7 · Smarter answers

GeoDNS & traffic steering

DNS can do more than return a fixed IP. The same name can resolve to different addresses for different users — to send them to a nearby data center, balance load, or route around an unhealthy region. How?

Authoritative NSreplicated · anycastGeoDNSnearest / weighted
New in this step: GeoDNS.

On the authoritative side, add GeoDNS / traffic management: return a different IP based on the resolver's location (nearest data center), server health (skip a down region), or weight (split traffic for a canary). This makes DNS a coarse global load balancer and failover mechanism — the first hop of routing users to the right place (exactly what a CDN leans on).

Why this piece earns its place

Steering answers a question it cannot quite ask: the authoritative server sees the resolver’s address, not the user’s. Someone on a large public resolver looks like wherever that resolver’s nearest node happens to be, which may be nothing like where they are — and the answer they get is then cached and handed to everyone else behind that same resolver. The unit of steering is a resolver’s user base, not a user. That is fine for coarse routing and misleading for anything that assumes precision. The partial fix is passing a truncated client subnet along with the query, and it costs on both sides: the cache now holds an entry per subnet instead of one per name, which eats into the hit rate that makes DNS cheap in the first place, and it tells every authoritative server roughly where the asker sits. Worth turning on for the latency-sensitive names and leaving off everywhere else.

What the new pieces do

GeoDNSservice
Traffic management on the authoritative side: return a different IP based on the asker's location or server health.

Step 8 · The sharp edges

Propagation, negatives, security

Real DNS has famous gotchas: changes that "haven't propagated," repeated lookups of names that don't exist, DDoS amplification, and the fact that a plain DNS answer can be forged.

Root Servers. → TLDTLD Servers.com → zoneAuthoritative NSreplicated · anycastGeoDNSnearest / weightedRegistrar / Zonerecord edits
New in this step: Registrar / Zone.

Propagation delay is just caching: a change is invisible until old TTLs expire, so you lower TTLs before a planned change. Negative caching remembers NXDOMAIN (name doesn't exist) so typos don't hammer the hierarchy. Defend against DDoS/amplification with anycast capacity and rate limiting. And DNSSEC cryptographically signs records so resolvers can detect forged answers (cache poisoning).

Why this piece earns its place

Signing changes a zone from fail-open to fail-closed, and that is the part to plan for. An unsigned zone with a mistake in it serves a wrong answer; a signed zone whose signatures have expired, or whose key no longer matches the record held one level up, serves nothing to validating resolvers while resolvers that do not validate carry on perfectly. It arrives as an outage only some users have, which your own checks may not reproduce. Signatures carry a validity window, so that is a clock running whether anyone is watching it or not, and key rollovers have to be coordinated with the level above rather than done alone. Signing also makes answers much larger, which pushes them past what fits in one UDP packet into truncation and a TCP retry, and makes the zone a more attractive amplifier for the reflection attacks named in the same breath — response rate limiting exists because of that, not despite it.

What the new pieces do

Registrar / Zonecontrol
Where the domain owner edits records. Changes propagate outward as caches expire — not instantly.

You did it

You just designed DNS.

ClientRecursive ResolverResolver CacheRoot ServersTLD ServersAuthoritative NSGeoDNSRegistrar / Zone
The finished design, end to end. · swipe to pan the diagram

Everything you assembled, in order

  • One central name→IP table fails on load, availability and control — so split and delegate it.
  • A recursive resolver does the multi-step walk so clients stay dumb (a stub resolver).
  • A delegated hierarchy: root → TLD → authoritative, each owning and pointing down one level.
  • Resolution follows referrals from the root hints down to an authoritative A record.
  • Caching with owner-set TTLs serves most lookups instantly and shields the hierarchy.
  • Replication + anycast make the root, TLDs and zones self-healing and DDoS-resistant.
  • GeoDNS steers users to nearby/healthy servers; DNSSEC, negative caching and low TTLs handle the edges.

Where an interviewer pokes next

Getting the boxes right is the easy half. These are the questions that separate a candidate who drew the diagram from one who has run the thing. Answer each one out loud before you open it.

  1. What actually happens in a single DNS lookup, end to end?

    Your app calls the OS, whose stub resolver forwards the question to a configured recursive resolver (your ISP's or something like 8.8.8.8). If the resolver has the answer cached and unexpired, it returns it immediately. Otherwise it walks the hierarchy: it asks a root server (whose addresses it knows from built-in root hints), which refers it to the .com TLD servers; it asks a TLD server, which refers it to the domain's authoritative nameservers; it asks an authoritative server, which returns the actual A/AAAA record. The resolver caches that answer for its TTL and hands the IP back to your machine. Most real-world lookups short-circuit at the cache and never touch the hierarchy at all.

  2. What does "DNS propagation" really mean and why isn't it instant?

    There is no push mechanism that updates the world when you change a record — DNS is pull-plus-cache. When you edit a record at your authoritative server, resolvers everywhere may still be holding the old value until its TTL expires. "Propagation" is just the wait for all those cached copies to age out and be re-fetched. That's why the standard playbook before a planned migration is to lower the record's TTL well in advance (say from a day to 60 seconds), make the change once caches are short-lived, then raise the TTL again. You're trading a temporary increase in query load for a fast, predictable cutover.

  3. Why are there only 13 root servers, and isn't that fragile?

    There are 13 root server identities (letters A through M) because that was the number of root nameserver addresses that fit in a single 512-byte UDP DNS response in the original protocol. But each identity is not one machine — it's an anycast cluster of anywhere from dozens to hundreds of physical servers spread across the planet, all announcing the same IP. A query to a root identity is delivered by network routing to the nearest instance. So "13" is a count of addresses, not servers; in reality there are well over a thousand root server instances, which is why the root has withstood massive DDoS attacks without a global outage — an attack saturates a few anycast nodes and traffic simply flows to the rest.

  4. How does DNS double as a load balancer and failover system?

    Because the authoritative server decides what to answer for a name, it can return different addresses to different queries. GeoDNS returns the IP of the nearest data center based on where the query came from; weighted responses split traffic (useful for canaries or gradual rollouts); and health-checked responses stop handing out the address of a region that's down, achieving failover. This makes DNS the coarse, global first hop of load balancing — it's exactly how a CDN steers you to a nearby edge. The limitation is TTL: since answers are cached, DNS-based steering and failover only take effect as fast as those TTLs expire, so anything needing fast failover uses short TTLs and is often paired with finer-grained mechanisms like anycast or an in-region load balancer.

  5. Why does DNS need DNSSEC — isn't a lookup harmless?

    A plain DNS answer is unauthenticated: a resolver believes whatever comes back, which historically let attackers forge responses and poison caches, silently sending users to malicious IPs for a real domain. DNSSEC adds a chain of cryptographic signatures from the root down to the zone, so a validating resolver can verify that an answer genuinely came from the zone's owner and wasn't tampered with — turning "trust the packet" into "verify the signature." It doesn't encrypt queries (that's DoH/DoT's job) or hide what you look up; it specifically guarantees integrity and authenticity of the records, closing the cache-poisoning class of attacks.

Check yourself — the answers, and why

Nine steps in, these are the calls you should be able to make cold. Pick one, then read why.

  1. A single central name→IP table can't work because…

    One table means one bottleneck, one failure point, and one owner of every name — all unacceptable.

  2. The recursive resolver exists so that…

    The stub client stays dumb; the resolver walks root→TLD→authoritative and caches for everyone.

  3. The DNS namespace is organized as…

    Each level owns its slice and refers one step down; no server knows everything.

  4. DNS feels instant mainly because…

    Owner-set TTLs let resolvers serve the vast majority of queries from cache, sparing root/TLDs.

  5. The root and TLD servers survive load and DDoS because…

    Anycast + replication turn each identity into a self-healing swarm routed around failure.

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

What it must do

Agree on these before drawing a single box.

  • Resolve a name: given vibeengines.com, return its IP address.
  • Delegate ownership: a hierarchy — root → TLD → authoritative — where each zone is independently owned.
  • Walk it for the client: a recursive resolver follows referrals so the stub client asks just once.
  • Cache with TTL: reuse answers for their owner-set TTL so most lookups skip the hierarchy.
  • Steer traffic: GeoDNS returns different IPs by location, health or weight — DNS as a coarse load balancer.

The qualities that shape everything

Each one names the mechanism that buys it.

No single owner or central bottleneck
Split the namespace into a delegated tree (root→TLD→authoritative); each level owns and points one step down, so no server holds everything.
Keep clients dumb
A recursive resolver does the whole root→TLD→authoritative walk and returns just the answer; the OS stub resolver asks it one question.
Feel instant, and shield the hierarchy
Resolvers cache each answer for its owner-set TTL, so the vast majority of lookups never touch root/TLD/authoritative at all.
Never go dark, survive DDoS
Replicate every level and front each address with anycast — one IP served from the nearest healthy machine, a dead node just routed around.
Send users to the nearest/healthy region
GeoDNS on the authoritative side returns different IPs by location, health or weight — a coarse global load balancer and failover.
Trustworthy answers on a hostile internet
DNSSEC signs records so resolvers detect forged answers; negative caching and low pre-change TTLs handle NXDOMAIN and propagation.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

Split & delegate the namespace over one central name→IP table

A single global table fails three ways at once — load (no machine serves the planet’s queries), availability (one thing to DDoS down), control (no entity should own every name). Hierarchy + delegation solves all three.

A recursive resolver over every device walking the tree itself

Making every stub device chase the hierarchy is wasteful and un-cacheable across users. One shared resolver walks the tree once and caches the answer for everyone behind it.

A delegated tree over a central directory of which server holds what

A directory of locations is just the central table one indirection removed. The name’s own dotted structure tells you where to go next, so the hierarchy needs no global index.

Cache answers for their TTL over walking the full hierarchy every lookup

A three-server walk per lookup would be slow and crush the root and TLDs. Caching for the owner-set TTL serves ~90%+ from the resolver — the same freshness-vs-load dial a CDN uses.

Replication + anycast over one hardened server per level

One box, however powerful, is still one target and one failure. Anycast (one IP announced from many places) turns each root/TLD/zone into a self-healing swarm — an attack hits one node and traffic flows to the rest.

The answer, out loud

What a strong answer to “Design DNS” sounds like, first question to last trade-off. It is about 7 minutes of talking; the whiteboard and the interviewer fill the rest of the 45. Read it aloud once, then close the page and give it yourself.

  1. 0–4 min

    What we are actually building

    Let me restate the problem so we agree on scope. I am designing the thing that turns a name a person can remember into an address a machine can connect to, for every domain on earth, with no single organisation in charge and no maintenance window. The functional ask is tiny — give me vibeengines.com, I give back an IP. Everything hard about it is non-functional. It has to absorb load no one machine could take, stay up while being attacked, and keep working while thousands of independent owners edit their own records whenever they feel like it.

  2. 4–9 min

    Killing the one-table design

    So I will start by killing the obvious design, because the whole architecture is a reaction to it. One server, one table of every name and address, everybody queries it. It dies three separate deaths. It cannot take the planet’s query rate, it is one thing to knock over, and whoever runs it decides which names exist. I care about the third as much as the first two — it is a political constraint rather than an engineering one, and it rules out every design where one party holds the whole namespace, however well that design scales.

    Built in step 1: One giant lookup table?
  3. 9–14 min

    Who does the legwork

    Before I split anything up I want to settle who does the work, because that shapes everything after it. If the answer lives in several places, someone has to visit them in order. I do not want that on every phone and laptop — it is fiddly, and nothing one device learns helps any other. So I will put a recursive resolver in the middle. Your machine keeps a tiny stub that asks one question and gets one answer, and the resolver does the walking and, more importantly, remembers what it learns on behalf of everyone using it.

    Built in step 2: The recursive resolver
  4. 14–21 min

    Letting the name route itself

    Now the split. I am not going to shard by hash or alphabet, because either way something still has to tell you which shard, and that something is the central table again. Instead I let the name carry its own routing. Read it right to left and every dot is a handoff. The root does not know your domain, it knows who runs dot com. Dot com does not hold your address, it knows which nameservers are yours. Yours hold the real records. Every level knows one step down and nothing else, and each zone is run by whoever owns it.

    Built in step 3: A delegated hierarchy
  5. 21–26 min

    One lookup, end to end

    The lookup then falls straight out of the structure. The resolver starts from addresses it already ships with, the root hints, otherwise there is no way to bootstrap. It asks a root server and gets referred to dot com. It asks dot com and gets referred to my nameservers. It asks one of mine, and that one answers instead of referring, because it is authoritative for the zone. Every server either knows or points one step down — nobody guesses — and the resolver keeps following pointers until someone finally claims to know.

    Built in step 4: Recursive resolution, step by step
  6. 26–33 min

    Why it is not slow

    That walk is far too expensive to do every time. It would be slow, and it would put the whole internet’s traffic onto the root and the TLDs, which is the central table again wearing a hat. So every record ships with a time to live, set by whoever owns it, and the resolver keeps the answer that long. The overwhelming majority of lookups then never leave the resolver at all — a hit, zero hops. And the cache is not only a speed trick, it is the load-shedding layer that makes the hierarchy survivable at all.

    Built in step 5: Caching with TTL
  7. 33–38 min

    Nothing here is one machine

    Availability next, since I have just made the root and the TLDs critical infrastructure. Nothing in this design is a single machine. Every zone runs at least two authoritative nameservers, and the addresses at the top are anycast — one address announced from many places at once, with the network delivering each query to the nearest instance. The thirteen root addresses are identities, not boxes, and each one is hundreds of machines. An attack lands on some of them and everybody else is simply routed elsewhere, which is why the root has never been globally downed.

    Built in step 6: Replication & anycast
  8. 38–43 min

    Answers that differ on purpose

    One more capability falls out almost for free. Because my own nameserver decides what to answer, it does not have to answer the same thing to everyone. It can return a nearby data centre’s address, weight the split to bleed traffic into a canary, or stop handing out a region that is failing its health checks. That makes DNS the first and coarsest layer of global load balancing — it is how a CDN puts you on a nearby edge. Coarse is the right word, though: the fine-grained work still belongs to a load balancer inside the region.

    Built in step 7: GeoDNS & traffic steering
  9. 43–45 min

    The trade, and what I would add

    To close on the trade-off: this is hierarchy plus caching, and the caching is what you pay for everything else. It is why a change is never instant — old answers live out their TTL, so you lower it before a migration — and why failover only moves as fast as the TTL you chose. With more time I would go into the hostile cases: signing records so a resolver can tell a forged answer from a real one, caching the fact that a name does not exist so typos never reach the hierarchy, and rate limiting so my nameservers cannot be pointed at someone else.

What this teaches

Learn system design by building the Domain Name System step by step. An interactive guide covering why one central name→IP table can't work, a delegated hierarchy of root / TLD / authoritative servers, recursive resolution, caching with TTL, replication and anycast for availability, GeoDNS and latency-based routing, and the unhappy paths (propagation, negative caching, DDoS, DNSSEC).

Key takeaways

  • One central name→IP table fails on load, availability and control — so split and delegate it.
  • A recursive resolver does the multi-step walk so clients stay dumb (a stub resolver).
  • A delegated hierarchy: root → TLD → authoritative, each owning and pointing down one level.
  • Resolution follows referrals from the root hints down to an authoritative A record.
  • Caching with owner-set TTLs serves most lookups instantly and shields the hierarchy.
  • Replication + anycast make the root, TLDs and zones self-healing and DDoS-resistant.
  • GeoDNS steers users to nearby/healthy servers; DNSSEC, negative caching and low TTLs handle the edges.

Concepts covered

  • What does DNS do?
  • One giant lookup table?
  • The recursive resolver
  • A delegated hierarchy
  • Recursive resolution, step by step
  • Caching with TTL
  • Replication & anycast
  • GeoDNS & traffic steering
  • Propagation, negatives, security
built to name the whole internet without a single owner — make the calls, drop the cache, run the gauntlet.
Finished this one? 0 / 65 System Designs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More System Designs