DNS changes don’t spread outward; old answers run out. Once your provider publishes an edit, its authoritative servers return the new data, but every resolver that cached the old answer keeps serving it until that copy’s TTL reaches zero. RFC 1034 defines the TTL in exactly those terms, as a limit on how long a record may be kept in a cache. So the useful question is not “has it propagated?” but “which cache still holds the old answer, and for how many more seconds?”

Start at the source: the authoritative answer

Live capture, 26 September 2026. One of and.guide’s two authoritative servers, queried directly with recursion turned off (DiG 9.10.6 on macOS, from South Korea):

dig @roan.ns.cloudflare.com and.guide A +norec
; <<>> DiG 9.10.6 <<>> @roan.ns.cloudflare.com and.guide A +norec
; (3 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15553
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;and.guide.			IN	A

;; ANSWER SECTION:
and.guide.		300	IN	A	172.66.44.244
and.guide.		300	IN	A	172.66.47.12

;; Query time: 11 msec
;; SERVER: 173.245.59.226#53(173.245.59.226)
;; WHEN: Sat Sep 26 23:36:31 KST 2026
;; MSG SIZE  rcvd: 70

Three details matter here:

  • flags: qr aa. The aa (authoritative answer) flag means the server answered from the zone itself, not from a cache. There is no rd flag because +norec asked the server not to recurse, and no ra flag because an authoritative-only server doesn’t offer recursion.
  • The TTL is 300, the value the zone publishes. Cloudflare uses 300 seconds both for its Auto setting and for every proxied record. An authoritative server hands out the full TTL every time; in the series below it returned 300 in all five rounds.
  • (3 servers found) is dig reporting that the nameserver’s name resolved to several addresses. The SERVER line shows the one it used.

Next, confirm that every authoritative server publishes the same version of the zone.

Live capture, 26 September 2026. The SOA record from both of our nameservers:

$ dig +nocmd @roan.ns.cloudflare.com and.guide SOA +norec +noall +answer
and.guide.		1800	IN	SOA	frida.ns.cloudflare.com. dns.cloudflare.com. 2414193944 10000 2400 604800 1800
$ dig +nocmd @frida.ns.cloudflare.com and.guide SOA +norec +noall +answer
and.guide.		1800	IN	SOA	frida.ns.cloudflare.com. dns.cloudflare.com. 2414193944 10000 2400 604800 1800

The third value in the SOA data, 2414193944, is the zone’s serial number, and both servers agree. Google’s Public DNS troubleshooting guide suggests this exact check when stale answers persist: if the serial changes from one query to the next, some authoritative servers may be serving old data, and waiting on resolvers will not fix that. The last value, 1800, returns below in the section on names that don’t exist yet.

A resolver’s TTL is the age of one cache

A recursive resolver’s answer shows how much longer its cached copy may be used. To see how that behaves in practice, we queried our apex repeatedly.

Live capture, 26 September 2026. Five rounds, 40 seconds apart, starting at 23:37:52 KST. Each round asked the authoritative server once, 1.1.1.1 twice, 8.8.8.8 twice, and our ISP’s default resolver once. Round four in full:

$ dig +nocmd @roan.ns.cloudflare.com and.guide A +norec +noall +answer
and.guide.		300	IN	A	172.66.44.244
and.guide.		300	IN	A	172.66.47.12
$ dig +nocmd @1.1.1.1 and.guide A +noall +answer
and.guide.		178	IN	A	172.66.44.244
and.guide.		178	IN	A	172.66.47.12
$ dig +nocmd @1.1.1.1 and.guide A +noall +answer
and.guide.		220	IN	A	172.66.47.12
and.guide.		220	IN	A	172.66.44.244
$ dig +nocmd @8.8.8.8 and.guide A +noall +answer
and.guide.		300	IN	A	172.66.44.244
and.guide.		300	IN	A	172.66.47.12
$ dig +nocmd @8.8.8.8 and.guide A +noall +answer
and.guide.		300	IN	A	172.66.47.12
and.guide.		300	IN	A	172.66.44.244
$ dig +nocmd and.guide A +noall +answer
and.guide.		219	IN	A	172.66.47.12
and.guide.		219	IN	A	172.66.44.244

All five rounds, as remaining TTL in seconds:

Round start (KST) Authoritative 1.1.1.1, 1st 1.1.1.1, 2nd 8.8.8.8, 1st 8.8.8.8, 2nd ISP default
23:37:52 300 300 299 300 300 300
23:38:32 300 300 300 300 300 300
23:39:13 300 218 300 260 300 300
23:39:53 300 178 220 300 300 219
23:40:33 300 220 300 300 220 117

What the numbers show:

  • One address, several caches. Two back-to-back queries to 1.1.1.1 in round four returned 178 and 220 for the same record, and 8.8.8.8 did the same thing in round five. A public resolver address is served by many machines. Google’s own description of its resolver names the problem: load balancers spread queries across machines, each of which would otherwise keep a separate cache, so Google adds a second cache level partitioned by name. Whatever the mechanism, consecutive queries to one address can disagree.
  • The countdown is not steady. A query that lands on a machine without the record fetches it fresh and reports the full 300.
  • We filled these caches ourselves. Every value below 300 except one traces back to one of our own rounds. The 178 at 23:39:53 means that cache fetched the record 122 seconds earlier, during our first round. The exception, the ISP resolver’s 117, points to about 23:37:30, shortly before the series, when we were trying out these commands against the same resolver. Looking up a name is enough to cache it: if you check the old record just before a cutover, you give those caches a fresh copy of the old answer for a full TTL.

Two practical rules follow. Sample each resolver more than once, and treat the authoritative answer as the check that decides whether your change is live. The DNS lookup tool shows Cloudflare’s and Google’s answers and TTLs side by side.

The TTL that counts was published before the change

When a record changes, caches holding the old version keep it for whatever TTL the old version carried. That is why lowering a TTL is preparation, done well ahead of the change itself.

Live capture, 26 September 2026. www.python.org publishes its CNAME with a one-week TTL. Here is that record at one of python.org’s authoritative servers and at three resolvers, in a single run at 23:41 KST:

$ dig +nocmd @ns-981.awsdns-58.net www.python.org CNAME +norec +noall +answer
www.python.org.		604800	IN	CNAME	dualstack.python.map.fastly.net.
$ dig +nocmd @1.1.1.1 www.python.org CNAME +noall +answer
www.python.org.		604800	IN	CNAME	dualstack.python.map.fastly.net.
$ dig +nocmd @8.8.8.8 www.python.org CNAME +noall +answer
www.python.org.		21219	IN	CNAME	dualstack.python.map.fastly.net.
$ dig +nocmd www.python.org CNAME +noall +answer
www.python.org.		146009	IN	CNAME	dualstack.python.map.fastly.net.

Reading the four answers:

  • 604800 seconds is seven days. If python.org changed this alias now, the ISP cache that answered us could keep serving the old target for another 146009 seconds, a little over 40 hours.
  • 1.1.1.1 had just fetched the record and could keep it for the full week.
  • 8.8.8.8 returned 21219, which is under 21600 seconds (six hours). Google’s FAQ says its cache lifetimes are generally limited to six hours even when the published TTL is longer.

The worst case therefore depends on the resolver, and you cannot count on a cap. Plan with the full TTL that was live before the change:

  1. Note the current TTL, for example 3600 seconds on a DNS-only record.
  2. Lower it, for example to 300, at least one old TTL (here, an hour) before the change.
  3. Confirm on every authoritative server that the lower TTL is being served.
  4. Make the change once. Caches now expire within the new, shorter window.
  5. Keep the old destination serving until that window has passed.
  6. Raise the TTL again once the new destination is stable.

The TTL planner turns these steps into a dated timeline. On Cloudflare, DNS-only records accept TTLs from 60 seconds (30 on Enterprise plans) up to one day, with Auto meaning 300, and proxied records are fixed at 300. Because a proxied record’s public answer is Cloudflare’s own addresses, switching the origin behind it doesn’t change what resolvers have cached at all.

Names that didn’t exist yet are cached too

A “does not exist” answer is cached like any other. RFC 2308 sets its lifetime to the smaller of two numbers from the zone’s SOA record: the record’s own TTL and its MINIMUM field, the last value in the SOA data. For and.guide both are 1800, so a negative answer can be reused for 30 minutes.

Live capture, 26 September 2026. A name under www.and.guide that doesn’t exist, and a name directly under the apex that we never created, at 1.1.1.1 and 8.8.8.8 (23:46 KST):

$ dig +nocmd @1.1.1.1 not-created-yet.www.and.guide A +noall +comments +authority | grep -E 'status:|SOA'
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 15865
and.guide.		1800	IN	SOA	frida.ns.cloudflare.com. dns.cloudflare.com. 2414193944 10000 2400 604800 1800
$ dig +nocmd @8.8.8.8 not-created-yet.www.and.guide A +noall +comments +authority | grep -E 'status:|SOA'
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 56130
and.guide.		1800	IN	SOA	frida.ns.cloudflare.com. dns.cloudflare.com. 2414193944 10000 2400 604800 1800
$ dig +nocmd @1.1.1.1 not-created-yet.and.guide A +noall +answer
not-created-yet.and.guide. 300	IN	A	115.68.101.36
$ dig +nocmd @8.8.8.8 not-created-yet.and.guide A +noall +answer
not-created-yet.and.guide. 300	IN	A	115.68.101.36

What to notice:

  • NXDOMAIN with the zone’s SOA record attached: both resolvers may reuse “this name does not exist” for up to 1800 seconds. If a hostname is looked up before you create it, users of that resolver can keep getting NXDOMAIN for up to half an hour after you do.
  • The second pair is not NXDOMAIN at all. Our zone has a wildcard record, *.and.guide, so an uncreated name directly under the apex receives the wildcard’s address with a 300-second TTL. Creating that name later replaces a cached positive answer, not a negative one. www.and.guide has its own records, and a wildcard never applies beneath an existing name, which is why the first pair failed.
  • We repeated these queries twice more, 45 seconds apart. Both resolvers reported the full 1800 and 300 each time, the same fresh-cache effect as in the series above.

The negative caching guide goes further into NXDOMAIN and NODATA answers, and the wildcard subdomains guide shows how our wildcard behaves at the DNS, TLS, and HTTP layers.

Where the disagreement lives

When answers disagree, find the layer before you change anything:

What you see Layer Next step
Authoritative servers return different data or different SOA serials Zone publication Fix it at the DNS provider; waiting won’t help
Authoritative servers agree, resolvers differ Caches of different ages Wait out the remaining TTL, or flush the public resolvers
Resolvers agree, one device differs Operating system, browser, VPN, or an open connection Clear that device’s cache or reconnect
DNS agrees everywhere, the site is still wrong Not DNS Check the host binding, certificate, and redirects

Flushing public resolvers, and the limits

Google Public DNS and 1.1.1.1 both let you ask for a cached name to be refreshed: Google through its Flush Cache page, Cloudflare through the Purge Cache page at one.one.one.one/purge-cache/. Google’s FAQ adds two caveats. For a stale CNAME chain, flush each CNAME starting from the last one in the chain and work back to the name you queried. Names served with EDNS Client Subnet cannot be flushed at all.

A flush affects only that one service. It does nothing for your ISP’s resolver, office resolvers, operating-system caches, or browsers, all of which wait out the TTL. Flush only after the authoritative data is right; otherwise you just cache the wrong answer again.

When it is no longer a DNS problem

The DNS side is done when every authoritative server returns the intended data and each resolver has either converged or shows a remaining TTL you understand. If the site is still wrong after that, look at the certificate, the host binding at the destination, redirects to an old environment, and stored webhook or callback URLs. The subdomain setup guide walks through those checks with real output.