Verifying DNS Propagation with dig Across Resolvers
Problem Statement
You have flipped the A record at the registrar or DNS provider and now need hard evidence that the change has reached real resolvers before declaring the cutover complete. Browser tests lie because of OS, browser, and local resolver caching, so you need authoritative confirmation from multiple independent public resolvers. This page is part of DNS Propagation Tracking and shows how to use dig to compare what each resolver currently serves and how long stale answers will persist.
When to Use This Approach
- You have just changed an A, AAAA, or CNAME record and need to confirm resolvers are serving the new value.
- Users report intermittent access — some see the new origin, some the old — and you suspect partial propagation.
- You lowered TTL ahead of the move (see How to Lower DNS TTL Before Migration) and want to confirm the short TTL is actually in effect.
- You need a scriptable, dependency-free check that runs from any Unix host without relying on third-party web tools.
- You must verify the authoritative answer matches what recursive resolvers cache before signing off the cutover.
Step-by-Step Instructions
1. Query the Authoritative Nameserver Directly
The authoritative nameserver is the source of truth — it answers with the record exactly as published, ignoring all recursive caches. Find the nameservers first, then query one of them by name so you are testing the real publication, not a cached copy.
# List the authoritative nameservers for the zone
dig example.com NS +short
# Query the new A record straight from an authoritative server (no recursion)
dig @ns1.example-dns.net example.com A +noall +answer
2. Query Public Recursive Resolvers
Recursive resolvers (8.8.8.8, 1.1.1.1) are what most users actually hit, and they cache answers for the duration of the record TTL. Query each one explicitly to see whether they still hold a stale answer or have picked up the new value.
# Google Public DNS — what a large slice of users resolve through
dig @8.8.8.8 example.com A +noall +answer
# Cloudflare 1.1.1.1 — second independent recursive view
dig @1.1.1.1 example.com A +noall +answer
# Quad9 for a third data point
dig @9.9.9.9 example.com A +noall +answer
3. Read the TTL Countdown to Predict Cache Expiry
The TTL value in a recursive resolver’s answer counts down toward zero on each subsequent query. A decreasing TTL means the resolver is serving a cached copy; when it hits zero it will re-fetch from authoritative. Poll the same resolver twice to see the countdown.
# First poll — note the TTL (second column)
dig @8.8.8.8 example.com A +noall +answer
# example.com. 286 IN A 203.0.113.10
# Wait, poll again — TTL has dropped, confirming a cached (not fresh) answer
dig @8.8.8.8 example.com A +noall +answer
# example.com. 241 IN A 203.0.113.10
4. Trace the Full Delegation Path
dig +trace walks the resolution chain from the root servers down through the TLD to the authoritative nameservers, bypassing recursive caches entirely. Use it when a resolver returns an unexpected answer and you need to confirm where in the delegation the wrong value originates.
# Walk root -> TLD -> authoritative, printing each delegation hop
dig +trace example.com A
# Restrict noise to just the final answer section while tracing
dig +trace +nodnssec example.com A
5. Confirm Old and New Origins Are Distinguishable
Before declaring success, prove you are reading the new IP and not a coincidental match. Compare the returned address against your known old and new origin IPs across every resolver, and only sign off once all recursive resolvers agree with authoritative.
# Loop the key resolvers and print each verdict in one pass
for r in 8.8.8.8 1.1.1.1 9.9.9.9; do
echo -n "$r -> "; dig @$r example.com A +short
done
Those five commands are not interchangeable, and knowing which one answers which question is most of the skill. Each queries a different point in the resolution chain, so a disagreement between two of them is information rather than a contradiction.
Worked Example
A move shifts example.com from a legacy origin at 198.51.100.20 to a new load balancer at 203.0.113.10. TTL was lowered to 300 seconds the day before.
Immediately after publishing the change, authoritative is correct but Google still serves the old value:
# Authoritative — already correct
$ dig @ns1.example-dns.net example.com A +noall +answer
example.com. 300 IN A 203.0.113.10
# Google 8.8.8.8 — still cached on the old origin, TTL counting down
$ dig @8.8.8.8 example.com A +noall +answer
example.com. 122 IN A 198.51.100.20
Roughly two minutes later, after the cached TTL expires, the recursive resolvers re-fetch and converge:
$ for r in 8.8.8.8 1.1.1.1 9.9.9.9; do echo -n "$r -> "; dig @$r example.com A +short; done
8.8.8.8 -> 203.0.113.10
1.1.1.1 -> 203.0.113.10
9.9.9.9 -> 203.0.113.10
All three recursive resolvers now match authoritative on 203.0.113.10, so this resolver set has fully propagated. Continued global confirmation belongs to Monitoring Global DNS Propagation During Cutover.
Reading the countdown is what turns a snapshot into a prediction. Because the TTL field decrements on each query against the same resolver, two polls a few seconds apart tell you not just whether the answer is cached but exactly how much longer the stale value will survive — which is the number you need in order to say when, rather than whether, that resolver will converge.
Script the pass condition rather than eyeballing it. A loop that prints addresses is fine while you are investigating and unreliable as a sign-off, because the thing you are checking for is the absence of an unexpected value — an extra A record left behind, a second address from a load-balanced set, an old AAAA — and absence is exactly what the eye skips over. Compare against an explicit expected set and fail on anything outside it.
Verification
# Pass condition: every resolver returns ONLY the new IP and nothing else
dig @8.8.8.8 example.com A +short | grep -qx '203.0.113.10' && echo "google OK"
# Confirm no stale AAAA record lingers if you also moved IPv6
dig @1.1.1.1 example.com AAAA +short
A clean result is every recursive resolver returning exclusively the new origin IP, with a TTL no larger than your lowered value, and dig +trace ending at the correct authoritative nameservers.
FAQ
Why does my browser still load the old site when dig already shows the new IP?
Browsers and operating systems keep their own DNS caches separate from public resolvers, and many hold answers for the OS-level minimum rather than the record TTL. Flush the OS resolver cache or test from an incognito session on a different network to confirm — dig against the public resolvers is the authoritative signal, not the browser.
What does the number after the record name in dig output mean? That is the remaining TTL in seconds for the cached answer at the resolver you queried. It counts down on each query against that resolver and, once it reaches zero, the resolver discards the entry and re-fetches from authoritative, which is exactly the moment propagation completes for that resolver.
Why does dig +trace sometimes disagree with dig @8.8.8.8?
+trace resolves fresh from the root and ignores recursive caches, so it reflects the current published record, while @8.8.8.8 reflects whatever Google has cached until its TTL expires. A disagreement simply means 8.8.8.8 is still serving a cached answer that has not yet timed out.
Is querying 8.8.8.8 from one machine enough to represent Google’s resolvers?
No. 8.8.8.8 is an anycast address served by many independent nodes worldwide, and each maintains its own cache, so the answer you get depends on which node your packets reached. A colleague on another continent querying the same address may legitimately get a different result for several minutes. That is why the parent DNS Propagation Tracking runbook samples from multiple regions rather than treating one query per provider as a verdict.
Why does dig sometimes return the right answer while curl still hits the old server?
Because they may not be resolving the same way. dig speaks directly to whichever resolver you point it at, while curl goes through the system resolver, which on modern Linux is often a local caching stub with its own entry. Add --resolve to pin curl to a specific address when you want to test the origin rather than the resolution path, and flush the stub cache when you want the two tools to agree.
Should I check AAAA records even if the site is IPv4-only today?
Yes, and specifically to confirm the absence of a stale one. A leftover AAAA record pointing at a decommissioned address is worse than no record at all, because dual-stack clients prefer IPv6 and will try it first, waiting for a timeout before falling back. The symptom is a site that feels inexplicably slow for a subset of users while every IPv4 check passes cleanly.
Related
- DNS Propagation Tracking
- Monitoring Global DNS Propagation During Cutover
- How to Lower DNS TTL Before Migration
← Back to DNS Propagation Tracking