DEV Community

Cover image for DNS Isn't a Phonebook. It's a Delegation Tree With a Cache Bolted On.
MANGESH MANDLIK
MANGESH MANDLIK

Posted on

DNS Isn't a Phonebook. It's a Delegation Tree With a Cache Bolted On.

You type example.com into a browser, and a moment later it's talking to a server somewhere on the internet. That transition feels almost too smooth to be interesting, but there's a real system doing work in between, and it's worth understanding on its own terms rather than as the thing you only think about when it breaks.

DNS gets called "the phonebook of the internet" often enough that the phrase has become the default mental model, and it's a reasonable starting point, but it hides most of what makes DNS actually work. DNS is a distributed, hierarchical, heavily cached naming system, and that design, not any single clever trick, is why billions of clients can resolve domain names without all of them depending on one enormous global database. I put together an interactive walkthrough of the whole resolution path on SeeItFlow, if you'd like to see it laid out visually rather than read it top to bottom.

There's no single server that knows everything

At the simplest level, DNS turns a name a human can read into information a machine can use: example.com goes in, 93.184.216.34 comes out. But there's no server anywhere holding every domain on the internet in one table. Responsibility is split across a hierarchy instead, and a lookup walks down through it: browser, to recursive resolver, to a root server, to the TLD server for .com, to the authoritative nameserver for example.com, which finally hands back the actual IP.

The reason this scales is that each layer only needs to know a little. The root doesn't need example.com's IP address, it just needs to know who's responsible for .com. The .com servers don't store every record for every .com domain, they just know which nameservers are authoritative for example.com. The authoritative nameserver is the only one that actually holds the real records. Responsibility gets delegated one level at a time, and that delegation is what lets DNS scale without any single organization maintaining global knowledge of the entire internet's names.

Recursive and iterative aren't two competing systems

These two words get mixed up constantly because they both describe the same lookup, just from different vantage points. When your machine asks a recursive resolver for example.com, it's essentially saying "give me the final answer, I don't want to deal with the hierarchy myself." That's the recursive part, from the client's perspective, one question goes out and one answer comes back.

What the resolver does next, though, is iterative. It asks the root server, gets pointed toward .com. It asks the .com server, gets pointed toward example.com's authoritative nameserver. It asks that nameserver and finally gets the actual IP. Each of those exchanges is the resolver getting the best answer a given server has, which is often just a referral to the next one down. The useful way to hold both ideas at once: client to resolver is recursive, the client hands off the whole problem, resolver to the rest of the hierarchy is iterative, the resolver does the legwork itself, one hop at a time.

Most lookups never reach the authoritative server at all

Walking root, then TLD, then authoritative nameserver for every single request would be enormously wasteful, and DNS avoids that through caching at nearly every layer it can. A lookup might get answered from the browser's own cache, or the operating system's cache, or the recursive resolver's cache, and only fall through to the actual DNS hierarchy if all of those miss. In practice, the overwhelming majority of lookups get served from a cache somewhere before they ever reach the domain's real authoritative server.

Every DNS record carries a TTL, time to live, that tells every cache along the way how long it's allowed to keep reusing the answer without asking again. A record with a TTL of 3600 seconds means a resolver can keep answering with that same IP for up to an hour without checking back in. That single number is behind one of DNS's more important production trade-offs: a long TTL means fewer queries and more cache hits, which is good for load and latency, but it also means changes take longer to actually reach everyone. A short TTL makes migrations and failover react faster, at the cost of more queries constantly landing on your DNS infrastructure. This is exactly why the standard advice is to lower a TTL well before a planned migration, not after, lowering it after you've already changed the IP does nothing for the copies of the old answer that resolvers cached while the TTL was still long.

"DNS propagation" is really just cache expiration, spread unevenly

Say you update api.example.com from 10.0.0.10 to 10.0.0.20. The new value can be sitting on the authoritative nameserver immediately, correct and ready to be served. And yet some users will keep reaching the old IP for a while, sometimes minutes, sometimes hours, depending entirely on what their particular resolver happened to have cached and when that cache entry's TTL runs out.

That's really the whole story behind what people casually call DNS propagation: the record changes at the authoritative server right away, some resolvers out there are still holding the old cached value, their TTL eventually expires, they ask again, and only then does the new value show up for whoever's using that resolver. There's no single moment when "the change propagates", there's a scattered set of moments, one per resolver, each governed by whenever its particular cached copy happens to expire. That's also exactly why the same DNS change can look instant to one person and take an hour to reach someone else, they're just hitting different resolvers with different cache states.

Why DNS mostly uses UDP, but not always

Most ordinary DNS queries are small, a hostname in, an IP out, so UDP is a good fit: send the query, get the response back, with very little transport overhead in either direction. And because a DNS query is safe to simply repeat if it goes missing, losing a UDP packet here and there isn't a serious problem, the client or resolver just asks again.

But "DNS uses UDP" isn't the complete picture. DNS falls back to TCP when a response is too large to fit in the space UDP allows, and TCP is also what's used for things like zone transfers, where an entire zone's records move between servers at once. The more accurate framing is that DNS commonly uses UDP for ordinary queries, but TCP is very much still part of the protocol whenever the situation calls for it.

A record isn't just a name pointing at an IP

DNS stores more kinds of information than most people realize. An A record maps a hostname to an IPv4 address, and AAAA does the same for IPv6. A CNAME points one hostname at another hostname rather than at an IP directly. MX records tell the world which mail servers handle a domain's email. TXT records hold arbitrary text, often used for domain verification or email security policies. NS records say which nameservers are authoritative for a zone, and PTR records do the reverse lookup, IP address back to hostname.

That range of record types is why "distributed database" is a more accurate mental model for DNS than "phonebook." A phonebook only ever maps a name to a number. DNS is storing several different kinds of structured, typed data, and different applications query different record types for entirely different reasons.

Two roles that get confused constantly

A recursive resolver does the actual lookup work on a client's behalf and caches whatever it finds along the way. An authoritative nameserver is the one that actually stores the real records for a zone, it's the source of truth, not a caching layer. If someone asks "which server actually stores my domain's records," the answer is always the authoritative nameserver, never the resolver. The resolver is just the caching middleman that goes and finds those records for you, and remembers the answer for a while afterward.

DNS is also a routing mechanism, not just a lookup

Once a system spans multiple regions, DNS starts doing more interesting work than simple name resolution. The same domain can resolve to different endpoints depending on where the request is coming from, a European visitor gets routed to an EU endpoint, someone in India gets an India endpoint, and DNS providers commonly support geo-based, latency-based, weighted, and failover routing to make that happen. Anycast takes a related idea further: the same IP address gets announced from many physical locations at once, and ordinary network routing carries a given request toward whichever announcing location is actually closest to it.

DNS round robin isn't a load balancer, even though it looks like one

A single hostname can resolve to several different IP addresses, api.example.com returning 10.0.0.1, 10.0.0.2, and 10.0.0.3 in rotation, and that does spread traffic across multiple servers in a rough sense. But DNS isn't sitting in the actual request path watching what happens to each request the way a real load balancer is. If one of those three servers becomes unhealthy, DNS has no immediate way to know or react, clients that already cached that IP will keep sending traffic to a dead server until their TTL expires, regardless of what's actually happening on the other end. This is exactly why production systems combine DNS-level routing with real load balancers and health checks, rather than treating round robin DNS as a full substitute for either.

Where this actually goes wrong

The protocol itself is rarely the hard part, it's the operational assumptions built on top of it that cause real incidents. The classic one: a team runs an infrastructure migration, changes an IP, and expects traffic to move over right away, only to discover the old record had a long TTL, so resolvers everywhere keep sending users to the old destination until those cached answers finally expire on their own schedule, sometimes hours after the "migration" was supposed to be complete.

A more dangerous version of the same underlying issue is a dangling DNS record, a CNAME still pointing at some third-party resource that's since been deleted or deprovisioned. If that external resource isn't yours anymore but your DNS record still points there, someone else can potentially claim that resource and effectively take control of your subdomain, a real subdomain-takeover vulnerability that starts entirely from an unmonitored, stale DNS entry.

DNS is also worth monitoring in its own right, not just assumed to be working silently in the background. Resolution latency, NXDOMAIN and SERVFAIL rates, unexpected record drift, domain expiry dates, and DNSSEC validation failures can all quietly degrade an application that looks completely healthy from every other angle.

DNSSEC and encrypted DNS solve different problems

Classic DNS has no built-in way to prove a response is authentic, nothing stops a response from being tampered with in transit. DNSSEC adds cryptographic signatures so a validating resolver can verify that the DNS data it received hasn't been altered along the way. What DNSSEC doesn't do is encrypt the query itself, someone watching the network can still see which domain you looked up, they just can't tamper with the answer undetected. Encrypted transport, DoH or DoT, solves that separate problem, hiding the query from anyone observing the network. DNSSEC is about authenticity and integrity. DoH and DoT are about privacy. They're not substitutes for each other.

A debugging habit worth having

When a DNS change looks like it's "not propagating," the first useful move is to ask the authoritative nameserver directly rather than guessing:

dig example.com @ns1.example.com
Enter fullscreen mode Exit fullscreen mode

If the authoritative server is already returning the new value, your configuration is correct and what you're actually looking at is a stale answer cached somewhere else in the chain, not a broken change. To see the entire resolution path as it actually happens:

dig +trace example.com
Enter fullscreen mode Exit fullscreen mode

And to check a specific record type against a specific resolver:

dig MX example.com @8.8.8.8
Enter fullscreen mode Exit fullscreen mode

These three commands cover a surprising share of real DNS confusion, most of it turns out to be a cache holding an old answer rather than anything actually misconfigured.

The model worth keeping

DNS isn't just "domain in, IP out." It's a distributed hierarchy, with delegation splitting responsibility across layers, typed records carrying more than just addresses, aggressive caching at nearly every layer a request passes through, TTLs deciding how quickly changes actually take effect everywhere, and a routing layer capable of sending different users to different places entirely. Once DNS looks like that instead of a simple lookup table, things like propagation delays, resolver caching behavior, CDN routing, and failover all stop being mysterious and start being the predictable consequence of a system built this way on purpose.

References

This post covers the resolution path and the core ideas behind it. The full walkthrough on SeeItFlow goes further into the resolution flow, caching layers, TTL behavior, and record types visually. There's also a dedicated production engineering guide covering migrations, dangling records, and monitoring in more depth, and an engineering insights guide focused on the trade-offs behind TTL choices, routing strategies, and DNSSEC.

Top comments (0)