DNSDNSresolverroot serversTLDauthoritative

DNS: Why Names Need a Distributed Database

Humans want engineer-atlas.dev, routers want 203.0.113.10, and no single file or server could hold the mapping for every name on earth — so DNS splits the namespace into a hierarchy of zones, delegates each to its owner, and lets a resolver near you walk that hierarchy and cache what it learns.

Conceptual
Interview question
Progress

The problem

The browser has engineer-atlas.dev. The IP layer needs a 32-bit or 128-bit number and nothing else. Who maintains the mapping for every name in the world, who is allowed to change the entry for *this* name, and how does your laptop get the answer in a few milliseconds?

Derive it: names for humans, numbers for routing

Routing needs numbers — prefixes that can be matched bit by bit and aggregated (The Routing Table and Longest-Prefix Match). Humans need names that survive the server moving to a different address. So there must be a mapping, and the question is only where it lives. The first answer, in the 1970s and early 1980s, was a single file: HOSTS.TXT, maintained at one institute and downloaded by every host on the ARPANET. Your /etc/hosts is its descendant.

A single file fails in three ways as the network grows. It is a single point of update — every change goes through one organisation. It is consistency-blind — hosts download it on their own schedule and disagree for days. And it does not scale — the file, and the traffic to fetch it, grow with the whole network. Replacing the file with a single server fixes nothing: one server for the world is one outage for the world and one queue for every lookup.

The design that survived (Mockapetris, 1983; RFCs 882/883, later 1034/1035) has three ideas. Hierarchy: names are a tree, read right to left. Delegation: each subtree — a zone — is run by its owner on its own servers, and the parent stores only who those servers are. Caching: answers carry a time-to-live so intermediaries can reuse them without asking again. Every property of DNS you will meet later, good or bad, follows from these three.

The hierarchy: root, TLD, authoritative

Read engineer-atlas.dev. from the right. The trailing dot is the root — usually omitted, always implied. Below the root sit the top-level domains: dev, com, de, io. Below dev sits engineer-atlas, a zone owned by whoever registered it. Below that, whatever the owner likes: www, api, eu.api.

Each level knows only its children. The root servers know which servers are authoritative for dev (and for every other TLD) — nothing else. The dev servers, run by the registry, know which servers are authoritative for engineer-atlas.dev — and nothing about what is inside it. The authoritative servers for engineer-atlas.dev hold the actual records: the address of www, the mail servers, and so on. The record that points a parent at a child’s servers is an NS record, and the act is delegation; see DNS Record Types and What They Are For.

The root is thirteen named servers (a.root-servers.net through m), but each name is anycast from many sites — well over a thousand physical instances in total — so the nearest one is usually a few milliseconds away. This is BGP anycast (Internet Routing: Autonomous Systems and BGP) doing the heavy lifting under DNS.

The namespace as a tree of zones
NSNSNS (delegation)A / AAAAA / AAAA. (root)dev (TLD registry)comengineer-atlas.dev (authoritative)wwwapi
UserLLMAgentToolDataDecisionHumanGuardrail

The resolver: your agent

Your application never talks to the root. It calls getaddrinfo() (or whatever the runtime wraps around it), which goes to the OS stub resolver: a small client that checks /etc/hosts, maybe a local cache, and then sends the question to a recursive resolver configured in /etc/resolv.conf or by DHCP — your ISP’s, your company’s, or a public one like 1.1.1.1 or 8.8.8.8.

The recursive resolver does the work. It asks the root, follows the referral to the TLD, follows the referral to the authoritative servers, gets the answer, caches every step, and returns the answer to you. "Recursive" describes what it does for the client (it takes on the whole job); the servers it asks along the way are iterative — they answer only "here is what I know, ask over there". Following One Lookup Through Every Cache follows one query through this chain.

The distinction that trips people up most: an authoritative server holds the truth for a zone and answers only about that zone; a recursive resolver holds no truth at all, only cached copies, and answers about anything. When you change a record, you change the authoritative server. Every resolver in the world will notice on its own schedule — this is the root of almost every DNS incident, and the subject of DNS Failure Modes: What Each One Looks Like.

  • Stub resolver: in the OS; tiny; asks one recursive resolver.
  • Recursive resolver: does the walk, caches, answers anything.
  • Authoritative server: holds the zone; answers only about its zone; never caches for clients.

On the wire

Conceptual

A DNS query is one message: a 12-byte header (a 16-bit ID the client uses to match the answer, flags, section counts), a question (www.engineer-atlas.dev, type A, class IN), and — in the response — answer, authority and additional sections holding records. It is carried in UDP on port 53 by default: one datagram out, one back, no handshake, which is why a cached answer costs one round trip and a stub-to-resolver query on a LAN takes under a millisecond. UDP: Datagrams and the Contract You Choose explains why this is the right transport here.

Answers were originally capped at 512 bytes over UDP. EDNS(0) raises that (resolvers commonly advertise 1232 bytes to stay under typical path MTUs and avoid fragmentation). If an answer still does not fit, the server sets the TC (truncated) flag and the client retries over TCP on port 53; zone transfers between authoritative servers always use TCP. So "DNS is UDP" is a default, not a rule, and a firewall that blocks TCP/53 will eventually break something — DNSSEC-signed responses and large TXT records are the usual victims.

The modern variants change the hop between *you and the recursive resolver*, which is the only hop a network observer can trivially read and tamper with. DoT (DNS over TLS, port 853) and DoH (DNS over HTTPS, port 443) encrypt it; browsers and phones increasingly use DoH to a resolver of their choosing, bypassing the OS configuration entirely — which is why resolv.conf and the browser can disagree about what a name resolves to. The resolver-to-authoritative hops are still mostly plain UDP.

A cached answer from a local resolver (dig, abbreviated)
$ dig www.engineer-atlas.dev A

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41337
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;www.engineer-atlas.dev.        IN  A

;; ANSWER SECTION:
www.engineer-atlas.dev.  287    IN  A   203.0.113.10

;; Query time: 1 msec
;; SERVER: 192.168.1.1#53(192.168.1.1) (UDP)

# flags: rd = recursion desired (we asked), ra = recursion available (it is a resolver)
# 287 = seconds of TTL remaining in this resolver's cache; the zone said 300

Why "the internet is down" is usually DNS

DNS runs before everything else. No name, no IP; no IP, no TCP connection, no TLS, no HTTP. A DNS failure therefore looks *total* — every site fails, every app fails — even though routing, transport and the servers are all fine. The tell is that things addressed by IP still work: ping 1.1.1.1 succeeds while ping google.com says "could not resolve host". Why Can’t I Connect? puts this at the top of its checklist for that reason.

It is also uniquely exposed to misconfiguration. It is the one piece of infrastructure that every engineer touches (adding a record for a new service) and few understand (the caching). Changes are made in one place and observed everywhere with delays that depend on caches nobody controls. And because it is "just UDP", it is what consumer routers, captive portals, corporate proxies and VPN clients all like to intercept. When something is broken for one person and not another, suspect DNS; when it is broken for everyone at once, suspect DNS first and routing second.

Key points

  • DNS exists because a central file or server cannot scale, cannot be consistently updated, and would be a single point of failure.
  • The namespace is a tree; zones are subtrees delegated to their owners; each level knows only its children via NS records.
  • Authoritative servers hold the truth for a zone; recursive resolvers hold cached copies and do the walking on the client’s behalf.
  • Transport is UDP/53 by default, TCP/53 on truncation and for zone transfers, DoT/DoH between client and resolver.
  • Caching with TTLs is what makes it fast and what makes changes propagate unevenly.
  • DNS failures look total because DNS comes first; things reachable by IP still work.

Why does this exist?

Mechanisms are answers to constraints. Open each question before reading the answer.

Why a hierarchy instead of one flat table?

So that ownership and update authority can be split: the dev registry does not need to know what is inside engineer-atlas.dev, and the owner of that zone can change it without asking anyone. A flat table would need one administrator for the world.

Why a resolver between me and the servers?

The walk from the root costs several round trips; a shared resolver amortises it across thousands of clients through its cache, and keeps the stub in every OS trivial. It is the same shape as a cache in front of a database.

Why UDP?

A query and its answer each fit in one datagram; a TCP handshake would triple the cost of the common case. Reliability is handled by the client retrying with the same ID, and TCP is there as the fallback for big answers.

How it fails

What the failure looks like from inside real software.

  • Resolver unreachable (VPN up, captive portal, resolv.conf pointing at a dead address): every hostname fails with a timeout after several seconds, ping 8.8.8.8 works, and the user reports "no internet".
  • TCP/53 blocked by a firewall: small answers work, DNSSEC or large TXT answers are truncated and the retry fails; the symptom is that only certain domains break.
  • Application using DoH while the OS uses split-horizon DNS: the browser resolves a corporate name to its public address (or NXDOMAIN) while curl on the same machine reaches the internal one.
  • Delegation broken at the parent (NS records at the registry point at servers that no longer host the zone): the zone works for anyone whose resolver has it cached and vanishes for everyone else as caches expire.
  • A wildcard or typo in /etc/hosts overriding a real name: one machine resolves differently from the whole world and no amount of dig @8.8.8.8 explains it, because dig does not read /etc/hosts.