You type example.com and press Enter. Before your browser sends a single byte of HTTP, before TLS starts, before any page content exists, something else has to happen first: your device has to work out where example.com actually is.
That job is DNS, and on an uncached lookup it often takes somewhere in the region of 20 to 150 milliseconds, depending on where you are and who you ask. The "50 ms" in the title is a rough middle, not a promise. It is also a delay that stacks up: a modern web page can touch dozens of domains, and every new one starts with the same question.
This guide follows one lookup from start to finish, so you know what is happening, where the time goes, and what you can measure and control.
Step 1: Your device checks its own memory first
The fastest DNS lookup is the one that never leaves your machine. Several layers get a chance to answer before anything touches the network:
- The browser's own cache. Browsers keep a short-lived list of recent lookups.
-
The operating system's stub resolver.
systemd-resolvedon many Linux systems,mDNSResponderon macOS and iOS, the DNS Client service on Windows. It keeps its own cache and decides which server to ask. - The hosts file. A manual override that wins over everything else. If any of these has a fresh answer, the cost is effectively zero. If not, the stub resolver sends the question out.
It is called a stub because it is deliberately simple: it does not do any real resolving. It just forwards the question to a recursive resolver.
Step 2: The question goes to a recursive resolver
Which server gets the question depends on your settings. Usually it came from DHCP, so it is your router, which forwards to your ISP's resolver. Some people point their device at a big public resolver instead. Others point it at a resolver they run themselves.
Two things matter at this hop:
- Distance. A resolver on your local network answers in a couple of milliseconds. One across the country does not.
- Transport. Classic DNS is plain text over UDP port 53, so anyone on the path can read it. DNS-over-TLS (port 853) and DNS-over-HTTPS (port 443) wrap the same question in encryption. The lookup itself is unchanged; only the envelope is. The recursive resolver is the part that does the real work, and it has a cache of its own.
Step 3: The resolver's cache usually saves the day
When the question arrives, the resolver looks in its cache. If another user asked for the same name recently and the record has not expired, you get the answer straight away, usually in under a millisecond of processing.
Expiry is controlled by the TTL (time to live) on each record. A site that sets a TTL of 300 is telling every resolver: you may reuse this answer for five minutes. Low TTLs let site owners move traffic quickly. High TTLs mean fewer lookups and faster responses.
Caches also remember negative answers. If you look up a name that does not exist, that "no such domain" result is cached too, for a period set by the zone's SOA record, so a typo does not trigger a full search every time.
Most of the time, this is where the story ends. The harder case is a cache miss.
Step 4: The walk, from the root down
On a miss, a recursive resolver starts at the top and works down, one referral at a time. For www.example.com it goes roughly like this:
-
Ask a root server: "Where is
www.example.com?" The root does not know, but it knows who runs.comand points you to those servers. -
Ask a
.comserver. It does not know either, but it knows which name servers are responsible forexample.com, and returns them. -
Ask the authoritative server for
example.com. This one holds the real record and returns the address. You can watch this happen withdig +trace. This is trimmed and the address is a documentation placeholder, but the shape is real:
$ dig +trace www.example.com
. 518400 IN NS a.root-servers.net.
...
com. 172800 IN NS a.gtld-servers.net.
...
example.com. 172800 IN NS a.iana-servers.net.
...
www.example.com. 300 IN A 203.0.113.10
Note the TTLs. Root and TLD referrals are cached for a long time (days), so in practice a busy resolver almost never contacts the root servers at all. It already knows who runs .com. A "cold" lookup for a domain nobody has asked about in a while usually costs just one or two network round trips, not three or four. That is why recursive resolving is faster in real life than it looks on paper.
Two refinements are worth knowing:
-
QNAME minimisation. A careful resolver does not send the full name to every server. The root only needs to know you are asking about
.com, not that you wantwww.example.com. Recent versions of Unbound do this by default, which limits how much each server on the path learns. - Glue records. If the name servers for a domain live inside that same domain, the parent zone supplies their addresses alongside the referral, avoiding a chicken-and-egg problem.
Step 5: DNSSEC adds a verification step
Plain DNS has no built-in way to prove an answer is genuine. DNSSEC fixes that with a chain of signatures: each zone signs its records, and the parent zone vouches for the child's signing key, all the way up to the root.
A validating resolver checks that chain. If a signature is wrong or missing where one is required, it returns an error instead of a forged answer. When validation succeeds, the response carries the AD (authenticated data) flag.
The cost is a few extra lookups for keys and signatures (DNSKEY, DS, RRSIG records), but those are cached too, so the overhead is small after the first few queries. One honest limit: DNSSEC proves an answer is authentic. It does not make it private. That is a separate job, handled by encrypted transport.
Where filtering fits in
Everything above describes a plain resolver. A DNS filter such as Pi-hole or AdGuard Home sits in front of the resolving step, between your device and the walk.
The filter checks the requested name against your blocklists. If it matches an ad network, a tracker, or a telemetry domain, the filter answers immediately with a "nowhere" response (typically 0.0.0.0 or NXDOMAIN), and no recursive walk ever happens.
That has a side effect that surprises people: a blocked lookup is usually faster than an allowed one, because it is answered locally with no network hop at all. On a page loaded with third-party trackers, that adds up, along with the bandwidth you no longer spend downloading them.
Only the allowed names continue down to the recursive resolver.
Putting numbers on it
Here is a rough picture of where time goes. These are typical ranges, not benchmarks, and your results will differ:
- Browser or OS cache hit: ~0 ms
- Your device to a local resolver: 1–10 ms
- Resolver cache hit: under 1 ms of processing
- Blocked by a filter: under 1 ms of processing
- Cache miss, one or two hops to authoritative servers: 20–150 ms
- First lookup after a record expires: same as a miss The slow case is rare but memorable. Unbound has settings that smooth it out: prefetch refreshes popular records shortly before they expire, so the next request still finds a warm cache, and serve-expired can briefly answer from an expired entry while it updates in the background.
Measure it yourself
You do not have to take any of this on trust. dig shows the time for each query:
dig example.com | grep "Query time"
Run it twice. The first run may be a cache miss, and the second should be close to instant. To test a specific resolver, name it directly. For example, a local Unbound listening on port 5335:
dig @127.0.0.1 -p 5335 example.com
To see the validation result, add +dnssec and look for ad in the flags line of a signed domain.
Who sees what along the way
Each hop learns something, and the picture changes depending on who you ask:
- Your ISP can read plain DNS on the wire, and often runs the default resolver.
- A large public resolver sees every name you look up, tied to your connection.
- Authoritative servers see only the resolver's address, not yours, plus whatever part of the name the resolver chose to send.
- A resolver you control that starts from the root means no single outside party sees your whole lookup history. Encrypting DNS hides your questions from the network between you and the resolver. It does not hide the IP address you then connect to, and in many cases the site name still appears in the TLS handshake. DNS privacy is one layer, not a cloak.
Running the whole chain yourself
Everything above can be assembled on a small server. A filter handles blocking, Unbound handles recursion and DNSSEC validation, and an encrypted endpoint carries the queries from your devices. We walk through the self-built version in Pi-hole with Unbound, and in Encrypted DNS Explained for the DoH and DoT side.
It is a good weekend project, and it is also a lot of small pieces to keep patched and certified. If you would rather skip that part, NxValue Stack runs this exact chain for you: your own isolated node with Pi-hole or AdGuard Home in front of Unbound, plus DoH and DoT endpoints already set up. It is billed hourly (the BASE-N plan is $4/month) and you can delete it at any time. You can look at a live dashboard in the demo node. It is shared publicly and meant for testing only, not personal use.
Either route gives you the same architecture. The difference is who does the maintenance.
Some limits to know about
- Your first visit to a rarely used domain can still be slow. A recursive resolver has to do the walk once. After that the cache takes over.
- DNS speed is not page speed. A faster lookup trims the start of a request, but it cannot fix a slow server or a heavy page.
- Filtering is not a full ad blocker. DNS cannot separate ads served from the same domain as the content, such as YouTube or Twitch video ads. A browser content blocker covers that gap.
- Aggressive blocklists can break things. A login page or a streaming app may stop working until you allow the domain. The query log shows you which name to look for.
-
A resolver you run is a point of failure. Always have a sensible fallback so the internet keeps working if it goes down.
Summary
Every request starts with a DNS lookup, and a cache hit makes it nearly free.
On a miss, a recursive resolver follows referrals from root to TLD to the authoritative server, though root and TLD answers are usually cached, so the real cost is often just one or two round trips.
DNSSEC proves answers are genuine; encrypted transport (DoT or DoH) keeps the question private on the way to the resolver.
A DNS filter answers blocked names immediately, which makes them faster than allowed ones.
You can measure all of it with
dig, and you can run the whole chain yourself, on your own hardware or on a managed node.
Pi-hole is a registered trademark of Pi-hole LLC. AdGuard Home is a trademark of AdGuard Software Limited. NxValue Stack is an independent service provider and is not affiliated with or sponsored by either project.
Top comments (0)