All chapters in this track
- 01Chapter 1: Why Networking Fundamentals Matter
- 02Chapter 2: The OSI Model and TCP/IP Stack, at a Working Level
- 03Chapter 3: Sockets, Ports, and the Connection Lifecycle
- 04Chapter 4: TCP vs UDP: Choosing the Right Transport
- 05Chapter 5: DNS Resolution, Step by Step
- 06Chapter 6: The HTTP Family: HTTP/1.1, HTTP/2, HTTP/3, and WebSockets
- 07Chapter 7: TLS/SSL and Certificates: The Handshake and Why HTTPS Matters
- 08Chapter 8: Load Balancers, Reverse Proxies, and CDNs
- 09Chapter 9: Latency, Bandwidth, and Congestion Control
- 10Chapter 10: API Protocol Choices: REST vs. gRPC vs. GraphQL, from a Networking Angle
- 11Chapter 11: Common Failure Modes: Timeouts, Connection Resets, Retry Storms, Thundering Herd
- 12Chapter 12: Where Networking Abstractions Leak: NAT, Middleboxes, and Other Surprises
- 13Chapter 13: Full Walkthrough: What Happens When You Type a URL and Press Enter
- 14Chapter 14: Common Networking Interview Questions
- 15Chapter 15: Networking Concepts in System Design and Production Debugging
Chapter 5 of 15
Chapter 5: DNS Resolution, Step by Step
Why this matters
DNS is arguably the single most "invisible until broken" piece of networking infrastructure — engineers interact with domain names constantly and think about the resolution process almost never, until a DNS misconfiguration causes an outage that looks, from the application's perspective, exactly like the entire internet has stopped working. Understanding the full resolution chain turns "DNS is down" from a vague, scary diagnosis into a precise, narrow one.
The core concept: why DNS exists
[BEGINNER] Computers route traffic using numeric IP addresses; humans need memorable names. DNS (Domain Name System) is the distributed, hierarchical system that translates a domain name (example.com) into an IP address, so that "distributed" and "hierarchical" aren't incidental design choices — they're what let DNS scale to the entire internet without any single server needing to know every domain name in existence.
The full resolution chain, step by step
[BEGINNER] Resolving www.example.com from a fresh machine with an empty cache involves several distinct servers, each responsible for a narrower slice of the answer:
1. Browser/OS checks its LOCAL CACHE first. If cached and not expired (per its TTL), done immediately.
2. If not cached, the query goes to a RECURSIVE RESOLVER (typically your ISP's, or a public
one like 8.8.8.8 / 1.1.1.1) — this server does the actual multi-step legwork on your behalf.
3. Recursive resolver asks a ROOT NAME SERVER: "who handles .com?"
Root server doesn't know the final answer, but knows who to ask next:
-> "Ask the .com TLD (Top-Level Domain) servers."
4. Recursive resolver asks a .com TLD SERVER: "who handles example.com?"
TLD server doesn't know the final IP either, but knows the next step:
-> "Ask example.com's AUTHORITATIVE NAME SERVER (at this specific address)."
5. Recursive resolver asks example.com's AUTHORITATIVE NAME SERVER:
"what's the IP for www.example.com?"
This server actually KNOWS — it returns the real answer: "93.184.216.34"
6. Recursive resolver returns this answer to your browser/OS, AND caches it
locally for this record's TTL, so step 3-5 aren't repeated for every request.
7. Your browser/OS also caches the result locally.
Your machine
|
v
Recursive Resolver <---- does all the legwork below, caches the final result
| ^
v (1) | (2: "ask TLD servers")
Root Server ---
|
v (3) ^
.com TLD Server -- (4: "ask example.com's authoritative server")
|
v (5) ^
example.com's Authoritative Server -- (6: "www.example.com = 93.184.216.34")
[IN PRACTICE] Every step in this chain is a real, separate network request (usually UDP, per Chapter 4) with its own latency — which is exactly why DNS caching at every level (browser, OS, recursive resolver, and the TTL that controls how long each cached answer is considered valid) matters so much for real-world performance: a fully "cold" resolution can take multiple round-trips before an application's very first byte of actual data can even begin to be requested.
Watching this happen, directly
[IN PRACTICE] The dig command shows exactly what a recursive resolver returns, including the TTL:
$ dig example.com
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34
;; Query time: 24 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
86400 is the TTL in seconds (24 hours) — this record won't be re-resolved from scratch until it expires, which is directly why DNS changes (like pointing a domain at a new server during a migration) can take time to fully propagate: any resolver that already cached the old answer will keep serving it until that cached TTL expires, regardless of how quickly the authoritative record was updated.
Common DNS record types
[BEGINNER]
| Record type | Purpose |
|---|---|
| A | Maps a name to an IPv4 address |
| AAAA | Maps a name to an IPv6 address |
| CNAME | An alias — maps a name to another name, which is then resolved in turn |
| MX | Specifies mail servers responsible for a domain |
| TXT | Arbitrary text — commonly used for domain ownership verification and email anti-spoofing records (SPF/DKIM) |
| NS | Specifies which name servers are authoritative for a domain |
Why DNS propagation delay is a real operational concern
[SENIOR INSIGHT] Because of caching at every level (Chapter 5's whole chain, plus the TTL mechanism), changing a DNS record doesn't take effect everywhere instantly — some resolvers, ISPs, or clients will keep serving a stale cached answer until their specific cached copy's TTL expires. This has a direct, practical operational consequence: before a planned migration (like switching to a new server's IP), lowering the record's TTL well in advance (e.g., from 24 hours down to 5 minutes, days before the actual cutover) ensures that by the time the migration happens, any caches have already refreshed to the low TTL, so the actual IP change propagates quickly rather than being stuck behind a long-cached previous TTL value.
Common mistakes
- Treating "DNS is down" as a single, monolithic failure without identifying which part of the chain actually failed — a misconfigured authoritative server, a recursive resolver issue, or a client-side cache serving stale data are very different problems with very different fixes.
- Forgetting to lower a record's TTL before a planned migration, resulting in a slow, unpredictable rollout as different caches expire their old (long-TTL) entries at different times over potentially a full day or more.
- Confusing a CNAME chain's added latency — each CNAME hop requires an additional resolution step (resolving the alias, then resolving what it points to) — with a "DNS is slow" problem unrelated to the actual chain length.
- Not distinguishing browser/OS-level DNS caching from the recursive resolver's caching when debugging a stale-DNS symptom — clearing one without the other can leave the problem only partially resolved, and different tools are needed to inspect/clear each (e.g., browser-specific internal DNS cache pages vs.
systemd-resolve --flush-cachesor OS-level cache clearing).
Checklist: reasoning about DNS in practice
- When diagnosing "the site won't load," resolve the domain independently with
digto check whether DNS itself is even the problem, before investigating TCP/TLS/HTTP-level causes. - Lower a DNS record's TTL well in advance of any planned migration, and only cut over once enough time has passed for the lower TTL itself to have propagated.
- Check
dig's reported TTL when debugging "I changed a DNS record and nothing happened" — a long TTL from before the change means existing caches are still serving the old value until it naturally expires. - When using CNAME chains, keep them short — each additional hop adds a real, if often small, resolution-latency cost, and can complicate debugging by adding indirection to trace through.
Discussion / interview questions
-
"Walk through what happens, step by step, when a recursive resolver resolves
www.example.comfrom a completely empty cache." Strong answer: Recursive resolver queries a root server (learns the .com TLD servers), queries a .com TLD server (learns example.com's authoritative server), queries that authoritative server directly for the actual answer, then returns and caches the result — the full chain from this chapter, in order. -
"Why does changing a DNS record not take effect everywhere immediately?" Strong answer: Caching at multiple levels (client, recursive resolver) means anyone with a still-valid cached copy (per the record's TTL) continues to see the old value until that TTL expires — not because the change itself was slow to apply at the authoritative server.
-
"What operational step should you take before a planned server migration that involves changing a DNS record?" Strong answer: Lower the record's TTL well in advance of the migration, and wait for that lower TTL to itself propagate, so that the actual IP change (once made) is picked up quickly by caches everywhere rather than being stuck behind a long previous TTL.
-
"What's the difference between an A record and a CNAME record, and what's a downside of long CNAME chains?" Strong answer: An A record maps a name directly to an IP address; a CNAME maps a name to another name, which must then itself be resolved — each additional CNAME hop in a chain adds another resolution step and a small amount of latency, and can make DNS debugging more complex to trace through.
Chapter summary / cheat sheet
- DNS resolution chain: local cache → recursive resolver → root server → TLD server → authoritative server → answer returned and cached at every level along the way, governed by each record's TTL.
digshows the actual resolved answer and its TTL directly — the first tool to reach for when diagnosing "is this actually a DNS problem."- DNS propagation delay is a direct consequence of caching + TTL — lowering TTL well before a planned migration is the standard operational mitigation.
- Common record types: A/AAAA (name → IP), CNAME (name → name), MX (mail servers), TXT (arbitrary text, often verification/anti-spoofing), NS (authoritative servers for a domain).
- "DNS is down" is rarely a single failure — identify which specific part of the chain (or which cache layer) is actually the problem before attempting a fix.