Dev March 14, 2026 9 min read

How DNS Actually Works: Address Bar to Server

Trace a DNS lookup step by step with real dig output, resolver caching behavior, and what happens when DNS goes wrong.

Last Tuesday my deploy went fine, tests passed, but the site was unreachable. Thirty minutes of debugging later, I realized the problem wasn't my code. A TTL that expired at exactly the wrong moment had caused my DNS records to briefly resolve to the old server IP, and every visitor got a connection timeout. The fix took two seconds: wait for propagation. But the panic took half an hour.

That experience pushed me to actually understand what happens between typing a URL and seeing a page. Not the hand-wavy "DNS translates names to IPs" explanation, but the full chain, complete with caches, timeouts, and the places where things break. Here's what I found.

Browser R Resolver . Root .com TLD IP Authoritative 93.184.216.34 (IP address returned) DNS Resolution Chain

What Happens When You Type a URL

You type example.com into your browser and press Enter. Before any HTTP request goes out, the browser needs an IP address. That lookup passes through multiple layers, each with its own cache and its own failure modes.

Step 1: Browser cache. Chrome, Firefox, and Safari all maintain an internal DNS cache. If you visited example.com recently and the cached entry hasn't expired, the browser skips everything below and connects immediately. Chrome shows its cache at chrome://net-internals/#dns.

Step 2: Operating system resolver. If the browser cache misses, the OS stub resolver takes over. On Linux this usually means systemd-resolved or /etc/resolv.conf. On macOS, the system resolver checks its own cache before making any network calls. Windows uses the DNS Client service.

Step 3: Recursive resolver. The OS forwards the query to a recursive resolver, typically your ISP's or a public one like 8.8.8.8. This resolver does the actual heavy lifting. If it doesn't already have the answer cached, it starts at the top of the DNS hierarchy.

Step 4: Root nameservers. There are 13 root server clusters (named a.root-servers.net through m.root-servers.net), operated by organizations including ICANN, Verisign, and the U.S. Army Research Lab. The recursive resolver asks a root server: "Where can I find .com?" The root replies with the addresses of the .com TLD nameservers.

Step 5: TLD nameservers. The resolver now asks a .com TLD server: "Who handles example.com?" The TLD server responds with the authoritative nameservers for that domain, like ns1.example.com.

Step 6: Authoritative nameserver. Finally, the resolver asks the authoritative server for the A record. It gets back an IP address, say 93.184.216.34, along with a TTL value. The resolver caches this answer and sends it back through the chain to your browser.

This full chain only runs on a complete cache miss. Most lookups short-circuit at step 2 or 3 because the recursive resolver already has the answer cached from a previous query by another user on the same network.

Seeing It Live

The dig command is the standard tool for inspecting DNS. Here's what a traced lookup looks like:

$ dig example.com +trace

; <<>> DiG 9.18.18 <<>> example.com +trace
;; global options: +cmd
.                  86400  IN  NS  a.root-servers.net.
.                  86400  IN  NS  b.root-servers.net.
;; Received 525 bytes from 127.0.0.53#53(127.0.0.53) in 1 ms

com.               172800  IN  NS  a.gtld-servers.net.
com.               172800  IN  NS  b.gtld-servers.net.
;; Received 1170 bytes from 199.7.83.42#53(l.root-servers.net) in 22 ms

example.com.       172800  IN  NS  a.iana-servers.net.
example.com.       172800  IN  NS  b.iana-servers.net.
;; Received 266 bytes from 192.33.14.30#53(b.gtld-servers.net) in 18 ms

example.com.       86400   IN  A   93.184.216.34
;; Received 56 bytes from 199.43.135.53#53(a.iana-servers.net) in 14 ms

Reading from top to bottom, you can see each delegation step. The root servers point to the .com TLD servers, those point to example.com's authoritative servers, and the authoritative server returns the final A record. The timing on the right shows each hop took 14-22ms.

For a quick lookup without the full trace:

$ dig example.com +short
93.184.216.34

$ dig example.com MX +short
0 .

$ nslookup example.com
Server:   127.0.0.53
Address:  127.0.0.53#53

Non-authoritative answer:
Name: example.com
Address: 93.184.216.34

The "Non-authoritative answer" label in nslookup means the response came from a cache, not directly from the authoritative server. That's normal and expected for most queries.

Want to check what a specific resolver returns? You can tell dig to query a particular server:

$ dig @8.8.8.8 example.com +short
93.184.216.34

$ dig @1.1.1.1 example.com +short
93.184.216.34

This is useful when you suspect a caching issue. If 8.8.8.8 returns your new IP but 1.1.1.1 still returns the old one, you know the record has propagated to Google but not yet to Cloudflare.

Caching: The Part That Bites You

Every DNS response includes a TTL (Time To Live) value, measured in seconds. A TTL of 3600 means "cache this answer for one hour." When you change a DNS record, the old answer doesn't disappear instantly. Every resolver that cached the previous response will keep serving it until the TTL expires.

There are at least three independent caches in the path:

  • Browser cache (typically 60 seconds for Chrome, varies by browser)
  • OS-level cache (controlled by the system resolver)
  • Recursive resolver cache (respects TTL from the authoritative server)

A common migration mistake: you have a TTL of 86400 (24 hours), you change the A record, and then wonder why half your users still see the old site a day later. The fix is to lower the TTL well before the migration. Set it to 300 (5 minutes) at least 24 hours in advance, so the old high-TTL records expire. Then make the change, and propagation happens within minutes instead of hours.

To flush your local DNS cache when testing:

# macOS
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder

# Windows
ipconfig /flushdns

# Linux (systemd-resolved)
sudo systemd-resolve --flush-caches

# Chrome browser cache
chrome://net-internals/#dns  → "Clear host cache"

Flushing your local cache only affects your machine. It won't change what your ISP's resolver has cached. You can work around that by switching to a different resolver temporarily, or just waiting out the TTL.

When DNS Goes Wrong

DNS is a single point of failure for the entire internet, and history has proven that more than once.

The 2016 Dyn DDoS attack. On October 21, 2016, the Mirai botnet flooded Dyn, a major DNS provider, with traffic from hundreds of thousands of compromised IoT devices. Twitter, GitHub, Netflix, Reddit, Spotify, and Airbnb all went down. Not because their servers failed, but because nobody could resolve their domain names. The attack came in three waves over the course of a day, and it demonstrated that DNS infrastructure concentration is a real risk.

DNS cache poisoning (the Kaminsky attack). In 2008, security researcher Dan Kaminsky disclosed a fundamental flaw in DNS. An attacker could race against legitimate responses to inject forged records into a resolver's cache. If successful, every user of that resolver would be silently redirected to a malicious server. The fix, source port randomization, was rushed out in a coordinated patch across all major DNS software. The full details are documented in RFC 5452.

Misconfigured TTLs. This one is quieter but far more common. A developer sets a TTL of 86400 for a production A record, then needs to do an emergency IP change. Now they're stuck waiting up to 24 hours for full propagation. Or the opposite: a TTL of 30 seconds on a high-traffic domain causes thousands of unnecessary queries per minute to the authoritative server, increasing latency and cost. Getting TTLs right is about matching the value to how often you expect the record to change.

Choosing a DNS Resolver

Your ISP assigns a default resolver, but you're not stuck with it. Here's how the main public options compare:

Resolver IP Address Privacy Policy Filtering DNSSEC
ISP default Varies Often logs and sells data Sometimes (varies) Inconsistent
Google Public DNS 8.8.8.8 / 8.8.4.4 Logs IP for 24-48h, then anonymizes None Yes
Cloudflare 1.1.1.1 / 1.0.0.1 No logging of source IP, audited by KPMG None (1.1.1.2 for malware filtering) Yes
Quad9 9.9.9.9 / 149.112.112.112 No personal data logging, Swiss jurisdiction Blocks known malicious domains Yes

For most people, switching from the ISP default to any of these three options will improve both speed and privacy. Cloudflare's 1.1.1.1 consistently benchmarks as the fastest in most regions. Quad9 is a good pick if you want built-in malware blocking without configuring anything. Google's 8.8.8.8 is the most widely used and tends to have the best cache hit rates because of its massive user base. For more on how Cloudflare's resolver works, their official documentation covers the architecture in detail.

DNS Records You Should Know

DNS isn't just about mapping names to IP addresses. There are several record types, each serving a different purpose. Here's a quick reference for the ones that matter most:

Record Purpose Example Value
A Maps domain to IPv4 address 93.184.216.34
AAAA Maps domain to IPv6 address 2606:2800:220:1:248:1893:25c8:1946
CNAME Alias pointing to another domain name www.example.com → example.com
MX Mail server for the domain 10 mail.example.com
TXT Arbitrary text (SPF, DKIM, domain verification) v=spf1 include:_spf.google.com ~all
NS Authoritative nameservers for the domain ns1.cloudflare.com
SOA Start of Authority: primary NS, admin email, serial ns1.example.com admin.example.com 2024010101

TXT records deserve special mention because they've become the Swiss army knife of DNS. Beyond SPF and DKIM for email authentication, services like Google Search Console and Let's Encrypt use TXT records for domain ownership verification. You'll also find DMARC policies there. If you're curious about the original specification that defined all of this, RFC 1035 from 1987 is still the foundational document.

One common gotcha with CNAME records: you can't place a CNAME at the zone apex. That means example.com can't be a CNAME, but www.example.com can. Some DNS providers (Cloudflare, for instance) work around this with a feature called CNAME flattening, which resolves the CNAME chain server-side and returns an A record to the client.

Lessons from the TTL Incident

Going back to my Tuesday outage: the root cause was simple. I'd migrated my site to a new server but hadn't lowered the TTL in advance. The old A record had a TTL of 3600, and my ISP's resolver had cached it 40 minutes before the change. So for the next 20 minutes, my machine kept connecting to the old IP. Once I understood the chain of caches involved, the mystery evaporated.

Here's what I do differently now:

  • Before any migration, lower TTLs to 300 seconds at least 24 hours ahead of time.
  • After changing records, verify propagation with dig @8.8.8.8 and dig @1.1.1.1 from multiple resolvers.
  • Keep a secondary DNS provider. If one goes down (as Dyn showed us), the other can still serve records.
  • Use dig +trace when something seems wrong. It shows exactly where the delegation chain breaks.

DNS is one of those systems that works so well most of the time that it's invisible. The problems only show up when caching, propagation, or infrastructure failures collide. Understanding the full resolution chain, from browser cache to authoritative server, turns a 30-minute panic into a 30-second diagnosis.

If you work with text configs and want to double-check the length of your DNS records or SPF strings, our text counter tool makes it easy to verify you're within the 255-character limit per TXT record string. And if you're dealing with YAML-based DNS configurations (common in infrastructure-as-code setups), our guide on YAML multi-line strings covers the quoting pitfalls that can silently break your records.

Analyze DNS records and zone files.