In short. Two resolvers giving different answers for the same name has four possible causes, and only one of them resolves itself with time. It is either the normal propagation window after a change, a deliberate split-horizon or geographic policy, or a genuine inconsistency between your own nameservers. Querying each authoritative nameserver directly separates them in one command.
Disagreement is expected briefly and a defect afterwards
DNS is a cache hierarchy, not a database. When you change a record, every resolver that already holds the old answer keeps serving it until its copy expires. During that window, different visitors legitimately get different addresses, and nothing is broken.
The mistake is treating every disagreement as that window. After the previous TTL has fully elapsed, continued disagreement is not propagation - it is a configuration difference, and waiting will not fix it. The first job is therefore to decide which of the two situations you are in, because they call for opposite responses: patience or investigation.
"Propagation" is a misleading word. Nothing is pushed anywhere. Each resolver independently discards its cached answer when the TTL expires and asks again. That is why the honest upper bound on a change is the TTL that was published before you made it - not the one you set afterwards.

The four reasons resolvers disagree
| Cause | Signature | Self-resolving? | Action |
|---|---|---|---|
| Propagation window | All authoritative NS agree; caches lag | Yes, within the old TTL | Wait; verify against authoritative |
| Split-horizon | Internal and external views differ by design | No | Confirm intent; check for leakage |
| Geographic or weighted answers | Answer varies by query source, consistently | No | Expected; verify the policy is correct |
| Nameserver drift | Authoritative NS disagree with each other | No | Fix the zone; this is a real defect |
Start by asking every authoritative nameserver directly
This single loop distinguishes the harmless cases from the defect. It bypasses every cache and asks each nameserver responsible for the zone what it believes.
for ns in $(dig +short NS example.com); do
printf '%-28s ' "$ns"
dig +short @"$ns" example.com A | tr '\n' ' '
echo
done
Two outcomes, and they mean completely different things:
- All nameservers return the same address. Your zone is consistent. Any disagreement you observed is caching, geography or a split view - not a broken zone.
- Nameservers return different addresses. This is a real defect. Your authoritative servers are not serving the same zone, and roughly half your visitors are being sent to the wrong place with no pattern you can predict.
Run the same comparison from outside your network with the DNS lookup, and use the propagation check to see what resolvers in different regions currently hold.
Telling propagation from a real inconsistency
If the authoritative servers agree, the remaining question is how much longer caches will disagree. The answer is written in the TTL, and you can watch it count down.
# Full record with its remaining lifetime at this resolver
dig example.com A @1.1.1.1 +noall +answer
# example.com. 212 IN A 203.0.113.10
# ^ seconds left before this resolver re-asks
# Ask again without triggering a fresh lookup - shows the cached copy only
dig example.com A @1.1.1.1 +norecurse +noall +answer
The number in the third column is the remaining lifetime, not the configured TTL. Repeat the query a few seconds apart: if it decreases, you are watching a cached answer expire and the disagreement has a known end. If it returns the full configured value every time, that resolver is fetching fresh and already agrees with your zone.
Lowering the TTL after a change does nothing for that change. Resolvers holding the old record honour the lifetime they were given when they cached it. To make a future migration fast, lower the TTL well before it - long enough beforehand that the old high value has already expired everywhere.
Split-horizon: intentional inside, accidental outside
Split-horizon DNS serves different answers depending on where the query comes from - typically a private address to internal clients and a public one to everyone else. It is a normal design, and it produces disagreement by definition.
The failure mode is leakage in either direction. An internal-only name that answers publicly discloses infrastructure. More disruptively, a public name that resolves to a private address for some clients sends them to an address that does not exist on their network - which looks exactly like an outage and is invisible from inside the office where everything works.
# What do you get from inside versus from a public resolver?
dig +short example.com A # your configured resolver
dig +short example.com A @1.1.1.1 # public resolver
# Does any public answer contain a private address? That is a leak.
dig +short example.com A @8.8.8.8 | grep -E '^(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.)' \
&& echo 'LEAK: private address served publicly'
A public record pointing at a private address is also one of the classic causes of proxy and CDN errors, because an edge cannot route to it. That path is covered in the origin error guide.

Geographic and weighted answers: disagreement as a feature
Providers that route users to the nearest or healthiest endpoint answer differently depending on where the query came from. Two resolvers in different countries returning different addresses is then correct behaviour, not a fault.
The signature that separates this from a problem is consistency: the same vantage point always gets the same answer, and the mapping is stable over time. Random variation from a single location is not geography, it is either round-robin or an inconsistency.
Two things are worth verifying even when the design is intentional. First, that every endpoint in the pool is actually healthy - a failover policy that keeps returning a dead address is worse than no policy. Second, that the resolver's own location, not the visitor's, is not driving the decision: many resolvers do not forward client subnet information, so users of a distant public resolver may be routed as if they were where that resolver is.
Nameserver drift: when your own servers disagree
This is the only cause in the table that is unambiguously a defect. If two authoritative nameservers for the same zone return different records, the answer a visitor receives depends on which server their resolver happened to ask.
The usual origins are a secondary that stopped transferring, a zone edited directly on one server instead of through the primary, or a leftover nameserver still listed in the delegation after a provider migration - the last being the most common and the hardest to notice, because the zone works perfectly until a resolver picks the stale server.
# Do the delegation and the zone agree about who is authoritative?
dig +short NS example.com # as delegated by the parent
dig +short NS example.com @$(dig +short NS example.com | head -1) # as the zone itself claims
# Do serial numbers match across all nameservers? They must.
for ns in $(dig +short NS example.com); do
printf '%-28s ' "$ns"
dig +short SOA example.com @"$ns" | awk '{print "serial", $3}'
done
# Follow delegation from the root, ignoring all caches
dig +trace example.com
Mismatched SOA serials across nameservers mean zone transfer is failing. Fix that before touching any individual record, because until the servers are synchronised every edit you make will apply to only some of them.
The TTL decides how long any disagreement lasts
| TTL range | Effect | Reasonable for |
|---|---|---|
| Very short (under a minute) | Fast changes, constant re-resolution, more DNS latency | Active failover, imminent migration |
| Minutes | Changes settle quickly, modest cache benefit | Records you expect to change |
| Hours | Good cache efficiency, slow to change | Stable A and MX records |
| A day or more | Best efficiency, painful to change in a hurry | NS, and records that genuinely never move |
The trade is between agility and lookup cost. A permanently tiny TTL means every visitor pays for a fresh lookup, which lands in the DNS stage of their TTFB. Lower it temporarily before a planned change and restore it afterwards - see the TTL guide for per-record recommendations, and the TTFB breakdown for how the lookup cost shows up in page timing.

A short procedure that covers all four causes
- Query every authoritative nameserver. Disagreement here is a defect; agreement clears the zone.
- Compare SOA serials. A mismatch means transfers are failing and nothing else should be changed first.
- Read the remaining TTL at a public resolver. Counting down means you are inside the propagation window.
- Compare answers from several regions. Stable per-region differences are geography; unstable ones are not.
- Grep public answers for private addresses. Any hit is a split-horizon leak.
How to check without a terminal
Use the DNS lookup to read records and TTLs from outside your network, and the propagation check to compare what resolvers in different regions return right now - which is what makes a regional pattern visible at all. The WHOIS lookup shows the nameservers currently registered at the registrar, which is the right place to catch a delegation still listing a provider you left.
For records that must not change silently - the address behind your main hostname, MX, or the NS set itself - a single check only proves the value was right when you looked. Scheduled DNS monitoring records the answer over time and alerts on change, which is how an unauthorised edit or an expired transfer gets noticed in minutes instead of on the day the mail stops arriving.

Frequently asked questions
How long does DNS propagation actually take?
At most the TTL that was published before you made the change, because that is the lifetime resolvers were given when they cached the old value. The frequently quoted "up to 48 hours" is a legacy of very long default TTLs and rarely applies to a zone with sensible values.
Two public resolvers disagree. Is my site broken?
Not necessarily. Check the authoritative nameservers first. If they all agree, you are looking at caching or geography and the site is fine. If they disagree with each other, that is a genuine defect and it affects a share of your visitors continuously.
Can I force resolvers to refresh?
Not for resolvers you do not operate. You can flush your own cache and your own recursive resolver, and some public resolvers offer a manual refresh for a specific name, but there is no mechanism to invalidate a cached answer across the internet. The TTL is the only control you have, and only in advance.
Why does the site work on mobile data but not on office Wi-Fi?
Different networks use different resolvers, so this is usually a caching difference or a split-horizon view. Compare the answer from your office resolver with a public one. If the office resolver returns a private address for a public name, you have found it.
What does a mismatched SOA serial mean?
That your nameservers are not synchronised. The primary has a version of the zone that at least one secondary has not received, so those servers answer from different data. Fix zone transfer before making any further record changes.
Should I keep TTLs permanently low so changes are always fast?
It is a real trade rather than a free win. Very low TTLs mean nearly every visit includes a fresh lookup, adding latency to the first request and load to your DNS provider. Lower TTLs ahead of a planned change and restore them once it has settled.
Checklist
- Ask every authoritative nameserver before concluding anything.
- Compare SOA serials across nameservers; a mismatch outranks every other symptom.
- Read the remaining TTL, not the configured one, to know how long caches will lag.
- Lower TTLs before a migration, never after.
- Check public answers for private addresses to catch split-horizon leaks.
- Treat stable per-region differences as geography, not as a fault.
- Verify the delegation at the registrar matches the nameservers your zone claims.
- Use
dig +tracewhen caches are making the picture unclear. - Monitor records that must not change silently, rather than checking them by hand.