You type example.com into your browser and hit enter. The page loads. It took maybe 200 milliseconds. You didn’t think about it.
In those 200 milliseconds, your query may have touched four different servers, walked a hierarchy designed in 1983, and relied on a caching system so aggressive that most queries never reach their destination. All of it invisible. All of it happening in the gap between your keypress and the first pixel on screen.
The Query Starts Closer Than You Think
Before anything touches the network, your machine checks the cheap answers.
The browser goes first: Chrome and Firefox keep their own small cache of recent lookups. If that misses, the browser asks the operating system, usually through getaddrinfo(), the standard library function that turns a hostname into addresses. (Some browsers, with DNS-over-HTTPS turned on, skip the OS and talk to their own resolver.)
The OS then checks /etc/hosts (on Windows, C:\Windows\System32\drivers\etc\hosts), a flat file that maps hostnames to IP addresses directly. It’s a relic from when the whole internet’s host list was one text file you downloaded. On a default setup it’s consulted before DNS, which is why it’s useful for local development and why malware sometimes modifies it.
Then the OS cache, if there is one: Windows’ DNS Client service, macOS’s mDNSResponder, systemd-resolved on many Linux systems. Did you look up this name recently? Is the cached answer still within its TTL? If yes, done. No network request. Sub-millisecond.
If nothing local has the answer, real DNS begins.
Your machine doesn’t do the full resolution itself. It delegates. The stub resolver, a lightweight DNS client built into your OS, takes the query and forwards it to a recursive resolver. Which one? Whatever is configured: your router, your ISP’s resolver, or a public one like 8.8.8.8 or 1.1.1.1.
The stub sends a small UDP packet: “What’s the A record for example.com?” Usually it sends a second one at the same moment asking for the AAAA (IPv6) record. Then it waits. Everything that follows happens on the recursive resolver’s side.
The Recursive Resolver’s Cache
The recursive resolver checks its own cache first. A busy public resolver like 8.8.8.8 serves an enormous number of users, so its cache is warm. If someone else asked for example.com recently, the answer is already there. Response goes back. Total time: the round trip to the resolver, often just a few milliseconds.
Most queries end here. The caching layer absorbs the vast majority of DNS traffic. If you’re accessing a popular domain, the recursive resolver almost certainly has a cached answer.
But say it doesn’t. Cache is empty. Now the resolver has to go find the answer from scratch.
Walking the Tree
DNS is a hierarchy. Root zone at the top. TLDs below (.com, .org, .net). Authoritative nameservers for individual domains below that. The recursive resolver walks this tree top-down.
First stop: the root. The resolver asks a root server, “What’s the A record for example.com?” The root doesn’t know — it doesn’t store individual domain records. But it knows who handles .com, so it responds with a referral: “Ask these nameservers.”
There are 13 named root servers, A through M, run by 12 independent operators. In reality there are close to 2,000 physical instances (root-servers.org counted 1,954 at the end of 2025), distributed worldwide using anycast — a routing technique where the same IP address is served by different machines depending on your location. When your resolver talks to “a root server,” it’s talking to whichever physical instance is closest. The resolver ships with the root addresses built in (they barely change), so this step is fast. One round trip. In practice a working resolver has the .com referral cached for up to two days, so it rarely has to ask the root at all.
Second stop: the TLD. The resolver asks a .com server. Same pattern: doesn’t have the final answer, but knows which nameservers are authoritative for example.com. Returns a referral. One more round-trip.
Third stop: the authoritative nameserver. The resolver asks directly. This server has the actual record. It responds with the IP address. Final round-trip.
The resolver caches the answer using the TTL (Time To Live) in the record, sends it to your stub resolver, which sends it to your application, which opens a connection to the IP (TCP, or UDP for QUIC).
Three round-trips for a fully uncached query. In practice, TLD referrals are almost always cached, so a “cold” query for a new domain under a common TLD usually needs one or two hops.
The 50 Millisecond Budget
Each round trip costs whatever the distance costs: a few milliseconds to a nearby anycast instance, a hundred or more to an authoritative server on another continent. A fully uncached lookup can run into the low hundreds of milliseconds. A partially cached one (the common case) is usually tens. A local cache hit is under a millisecond. That’s where the 50 in the title comes from: it’s a typical budget, not a law.
This is why TTLs matter. A 300-second TTL (5 minutes) means the resolver re-queries every 5 minutes. A 86400-second TTL (24 hours) means once a day. Shorter TTLs mean fresher data but more latency on expired caches. Longer TTLs mean faster responses but slower propagation when you change records.
When people say “DNS propagation takes 24-48 hours,” what they actually mean is caches around the world are holding the old answer until the TTL expires. There’s no propagation mechanism. Old caches just expire at different times. The 48 hours is not folklore, either: the .com registry publishes its NS records with a two-day TTL, so a nameserver change can take that long to be seen everywhere.
What Can Go Wrong
At each step, things can fail.
NXDOMAIN. The domain doesn’t exist. The authoritative server says so. Clean failure.
SERVFAIL. The resolver tried to get an answer and couldn’t. Maybe the authoritative server is down. Maybe DNSSEC validation failed. Maybe there’s a network issue. SERVFAIL is the generic “something broke” response, and debugging it means tracing the query at each hop.
Timeout. The resolver sent a query and got nothing back. After a few seconds it retries, often against a different server. If all timeout, the query fails. The user sees a browser error page.
Poisoned cache. An attacker injects a fake response into the resolver’s cache. Everyone who queries that domain gets the fake answer. This is what DNSSEC prevents — and what makes its low adoption frustrating.
The Invisible Machine
DNS is one of the oldest protocols still running at the core of the internet. Designed when the entire network could be mapped in a single document. Now carrying the lookups for nearly everything that happens online.
Most developers use it hundreds of times a day without a second thought. The URL goes in, the page comes up, and the 50 milliseconds in between might as well not exist.
But they do exist. And the next time a page loads slowly for no obvious reason — check DNS first. The invisible machine might be stuttering.