All posts

There is no DNS propagation

The nameserver had the new address in 0.017 seconds. Eight caches kept the old one until the TTL they stored ran out, the last at 60.5 seconds.

Written by NodeRings Inc.

NodeRings Inc. writes these notes. The company runs the marketplace and the agent that stays on the provider’s side of the hypervisor.

NSD 4.8.0 answered 192.0.2.20 for t60.lab.invalid 0.017 seconds after the reload. The packet had the AA flag and a TTL of 60, the full value just written. Eight copies of Unbound 1.19.2 on the same machine were still answering 192.0.2.10.

They had been primed five seconds apart, so the timers already in those caches were 25, 30, 35, 40, 45, 50, 55, and 60 seconds. The cache holding 25 seconds returned the new address at 26.3 seconds, one poll after its stored TTL hit 0. The cache that had just learned the old address returned the new one at 60.5 seconds. For the half minute between those two samples, both addresses were live. A checker that queries several resolvers shows both for that stretch. The nameserver had finished, and each cache was spending a timer it saved before the reload.

Dig was 9.18.39. NSD listened on 127.0.0.1 port 5453. Each Unbound listened on its own port from 5401 to 5408, with lab.invalid stubbed at that NSD. serve-expired was no, cache-min-ttl was 0, and prefetch was off. Unbound ships a built-in zone for invalid. that answers NXDOMAIN by itself, so the config turns it off with local-zone: "invalid." nodefault. Without that line Unbound answers from the built-in zone and the stub sits idle. The addresses are from the documentation range in RFC 5737.

A stub asks a recursive cache that still holds 192.0.2.10 with 25 to 60 seconds left. The authoritative server already answers 192.0.2.20.
Eight Unbound caches, primed five seconds apart, against one NSD. The new address was ready in 0.017 seconds. The caches moved between 26.3 and 60.5 seconds.

Why a propagation checker shows two answers

whatsmydns.net keeps resolvers in a lot of countries and draws the answers on a map. The page uses the word propagation for that map, and the mechanism it describes is a cache. The resolver asks the authoritative server when it has to, then holds the answer for the TTL. Different answers on that map are caches that learned the old record at different moments, so they expire at different moments.

The 300 second run had the same shape, with the primes 20 seconds apart. At the reload the eight remaining TTLs were 160, 180, 200, 220, 240, 260, 280, and 300. The first new answer showed up at 161.0 seconds. The last showed up at 300.3 seconds. The authoritative lag on that reload was 0.017 seconds again.

The 3600 second record was primed all at once, so the eight caches agreed with each other and disagreed with the nameserver. At 180.3 seconds, 0 of 8 had moved to 192.0.2.60. They were still serving 192.0.2.50 with about 3,420 seconds left. I stopped the sample there, and the chart stops the line with it.

PortSeconds left at the reloadNew address, TTL 60
54012526.3 s
54023030.8 s
54033535.4 s
54044041.1 s
54054545.7 s
54065050.2 s
54075555.9 s
54086060.5 s

The poll was about 1.1 seconds, so each of those times is the first sample after the stored TTL hit 0. The cache then stored the new address with a fresh TTL of 60.

On the public side, from this host, one site of each anycast resolver. example.com A at hera.ns.cloudflare.com came back with the AA flag, TTL 300, 104.20.23.154 and 172.66.147.243, in 26 ms. The same name at 8.8.8.8 was those two addresses with 291 seconds left, in 38 ms. At 1.1.1.1 the remainder was 154 seconds, in 31 ms. At 9.9.9.9 it was 185 seconds, in 27 ms. One authoritative TTL, three remainders.

I also asked 8.8.8.8 for example.com twice, ten seconds apart, four times. The address set stayed the same and the remaining TTL went up, by 19, 41, 75, and 96 seconds. Query times were 19 to 38 ms, so those were hits on different caches. Anycast will do that. A rising TTL from one public address stays out of a countdown chart.

ans1.nrings.io at ns1.nrings.io was AA, TTL 300, 23.139.228.18, in 170 ms. The same name at 8.8.8.8 also came back at TTL 300, after 1,185 ms. A full TTL next to a slow query is a fetch. The lab pair below is the one where a single cache counted down: authoritative TTL 3600 on the new address, and the resolver still on the old address, 3587 seconds and then 3572, fifteen seconds of wall clock later.

Dig against the lab nameserver shows TTL 3600 and 192.0.2.60. The same name at a local resolver shows 3587, then 3572, still on 192.0.2.50. example.com is TTL 300 at the authoritative server, 291 at 8.8.8.8, 154 at 1.1.1.1, and 185 at 9.9.9.9.
Top: one cache, fifteen seconds, the TTL fell by fifteen and the address stayed old. Below: example.com at the authoritative server and at three public resolvers, queried from this host.

How long a DNS change takes

The last cache in the 60 second run waited 60.5 seconds because that was the TTL it had stored. The last cache in the 300 second run waited 300.3 seconds for the same reason. The 3600 second caches still had about 3,420 seconds to go when the sample stopped at 180. Shortening the TTL after the address has already changed leaves those stored timers alone. The new TTL applies to the next fetch.

Set the short TTL first. Wait out one full period of the previous value. Then change the address. A resolver that learned the record a second before you shortened it is still holding the long timer. If that previous value was 86400, the wait is a day, and the 60 you just published starts only when that resolver comes back.

On NodeRings hosted DNS a record TTL has to sit between 30 and 86400 seconds. That limit is in the DNS guide. Geo records, the A, AAAA, CNAME, NAPTR, and SRV rows, are 30 to 60 seconds, because the answer is a choice about who asked and a long cache pins the previous city. GeoDNS follows the resolver is that choice. The GeoDNS guide states the 30 to 60 range.

The mail TXT records in SPF, DKIM and DMARC are published at 3600, inside the range the console allows. A selector rotation waits out those 3600 seconds when that is the TTL already cached. 86400 is the top of the allowed range, for a record you mean to leave alone. 60 is the value to publish before a move, once the previous timer has aged out. 300 sits in the middle: long enough that a quiet name is usually a cache hit, short enough that a planned move is over in five minutes once the old timer is gone.

TimerSeconds
Lab A, TTL 60First cache at 26.3 s, all eight at 60.5 s
Lab A, TTL 300First cache at 161.0 s, all eight at 300.3 s
Lab A, TTL 36000 of 8 at 180.3 s, about 3,420 s still left
NodeRings record30 to 86400, set in the zone
GeoDNS30 to 60
example.com, google.com, cloudflare.com NS172800 at a.gtld-servers.net
nrings.io NS3600 at a2.nic.io
Lab negative cacheSOA TTL 30, new name at 30.6 s
example.com negative answerSOA TTL 1800 at hera.ns.cloudflare.com
nrings.io negative answerSOA TTL 300 at ns1.nrings.io
Step chart of eight local caches. TTL 60 reaches 8 of 8 at 60.5 seconds. TTL 300 reaches 8 of 8 at 300.3 seconds. TTL 3600 is still 0 of 8 at 180 seconds.
Eight Unbound processes on one machine. The 60 and 300 series were primed apart, so they expired apart. The 3600 series was primed together and was still on the old address when the sample stopped.

A nameserver change waits on the parent

The NS set at the parent is a different record from the NS in your zone, and a different timer. I asked a.gtld-servers.net for the delegation of example.com, google.com, and cloudflare.com. Each one came back with TTL 172800. dig +ttlunits prints that as 2d. Query time on example.com was 120 ms, and the server was 2001:503:a83e::2:30. That number lives at the registry. A smaller NS TTL saved in the zone leaves the parent's 172800 in place.

nrings.io at a2.nic.io came back at 3600 for ans1.nrings.io, ans2.nrings.io, ns1.nrings.io, and ns2.nrings.io, in 41 ms. That parent TTL is an hour. The three .com delegations were 48 hours. whatsmydns.net tells readers to allow 48 to 72 hours for a change that is taking a long time.

The nameservers to put at the registrar, for a zone hosted here, are ans1.nrings.io and ans2.nrings.io, on their own. ns1 and ns2 are the unicast names for dig @ns1.nrings.io. The DNS guide says the same thing.

If the domain is signed, the parent also holds a DS. The guide says to remove that DS at the registrar and wait until it is gone, up to 48 hours, before changing nameservers. Leave it and resolvers return SERVFAIL. That failure is the registrar still trusts the old key. The 172800 above is the NS delegation, measured on its own.

Dig of example.com, google.com, and cloudflare.com NS at a.gtld-servers.net, each with TTL 172800. nrings.io NS at a2.nic.io with TTL 3600.
Three .com delegations at a.gtld-servers.net, all TTL 172800. The nrings.io delegation at a2.nic.io is 3600.

A missing name stays missing

The first query for fresh.lab.invalid came back NXDOMAIN, with the SOA at TTL 30. That 30 is the MINIMUM in the zone and the TTL on the SOA record itself. RFC 2308 sets the negative cache TTL to the lesser of those two. I then added fresh.lab.invalid as 192.0.2.70. The authoritative server had the A record in 0.038 seconds. The resolver that had stored the absence returned the address at 30.6 seconds, with TTL 60, the TTL on the new A record.

The nameserver was already serving the name. The resolver was serving the NXDOMAIN it had stored, and it kept that until the negative timer hit 0. Asking it again, or adding the record a second time, finds the same cache.

A missing name under example.com, asked at hera.ns.cloudflare.com, came back NXDOMAIN with the SOA at TTL 1800. The MINIMUM inside that SOA is also 1800. Query time 19 ms. A missing name under nrings.io, asked at ns1.nrings.io, came back NXDOMAIN with the SOA at TTL 300, in 162 ms. The MINIMUM field in that SOA is 3600, and the TTL on the SOA record is 300, so the negative answer is offered at 300. Both queries went straight to the authoritative server.

Who keeps the TTL you published

Unbound 1.19.2, with cache-min-ttl at 0 and serve-expired off, counted the stored TTL down about one second per second and fetched when it hit 0. In the 60 second CSV, port 5401 goes from TTL 25 on 192.0.2.10 to TTL 0, and on the next poll to 192.0.2.20 with TTL 60.

Google's Public DNS FAQ says cached TTLs are generally limited to six hours even when the published TTL is longer. A record at 86400 can leave that cache on the shorter timer. The clamp is a shorter timer than the one in the zone. The same FAQ has a flush tool. It asks for a reCAPTCHA and skips any ownership check. After a nameserver change, flush the NS before names underneath it, or the flush refreshes them from the old servers. Names that use EDNS Client Subnet are left out of the tool.

Cloudflare's 1.1.1.1 page says the resolver caches an entry for up to 3 hours, and a shorter TTL is kept as published. The purge tool on that page pushes a flush through Cloudflare's own data centers in a few seconds. That push stays inside their resolver. 8.8.8.8 and the resolver in the office still have whatever they stored.

RFC 8767 lets a resolver serve an expired record when a refresh fails, and it names Unbound among the packages with the option. This lab left serve-expired off, and NSD stayed up, so the stale path stayed unused.

On Cloudflare's own DNS, a proxied record is fixed at TTL 300. Their TTL page says a local cache can outlast those five minutes. An unproxied record can be set from 60 seconds, or 30 seconds on an Enterprise account, up to a day. Auto is 300 there too. If the name is proxied, the address in DNS is an edge address. Changing the origin is a change in the proxy, on a different timer from this one.

Commands that skip the cache

dig example.com A @hera.ns.cloudflare.com +norecurse
dig example.com A @8.8.8.8
dig example.com NS @a.gtld-servers.net +norecurse
dig +ttlunits example.com NS @a.gtld-servers.net +norecurse
dig +trace example.com
dig ans1.nrings.io A @ns1.nrings.io +norecurse
dig nrings.io NS @a2.nic.io +norecurse
resolvectl flush-caches

+norecurse asks the server you named to answer from what it already holds. On an authoritative server the AA flag means it is the source, and the TTL is the full value. On 8.8.8.8 the flags are qr rd ra and the TTL is the remainder in whichever cache took the query. +trace walks from the root to the authoritative server, and the answer in that output came from the servers on the path. resolvectl flush-caches clears systemd-resolved on the machine you run it on. chrome://net-internals/#dns is the browser's own cache, which sits in front of the stub.

FAQ

Does flushing the local cache help?

It clears the cache you flushed. resolvectl flush-caches is the stub on that machine. The browser has another one. 8.8.8.8, 1.1.1.1, and the resolver a phone got from the carrier are still holding what they stored. Google's flush tool covers Google Public DNS, with the limits above. It leaves every other resolver on its own timer.

Does a Cloudflare proxy change the wait?

The proxied TTL is fixed at 300 seconds, and a cache in front of that can hold the edge address for longer. An origin change on a proxied name is applied at the proxy. The DNS TTL is the wait for the edge address itself, which you usually leave alone.

Why is the GeoDNS TTL 30 to 60 seconds?

The answer depends on the resolver that asked, and sometimes on a client prefix that resolver attached. A long TTL pins the previous city for everyone sharing that cache entry. The measurement and the prefix rules are in GeoDNS follows the resolver.

Can I force every resolver onto the new record?

Shorten the TTL before the change, then wait out the old one. A few operators let you flush their cache. Google's tool is one, and it skips ECS names. The eight Unbound processes here moved when the timer they had stored hit 0: 26.3 seconds for the first, 60.5 for the last, 161.0 and 300.3 on the 300 second run.

Why does a phone disagree with a laptop?

They ask different resolvers, or the same public address through different anycast sites. From one host, 8.8.8.8, 1.1.1.1, and 9.9.9.9 held 291, 154, and 185 seconds on the same example.com addresses. A phone and a laptop can land on two of those.

For a record change, plan against the TTL that was already cached. In this lab that was 60.5 seconds when the TTL was 60, and 300.3 seconds when it was 300. For a .com nameserver change, the parent TTL at a.gtld-servers.net was 172800.