nothing propagates, caches expire·the TTL is one you set yourself·negative caching per RFC 2308·the 48-hour number is not superstition

Nothing propagates, caches expire

The mental model in almost every support article is wrong. There is no wave of updates rolling across the internet, no queue of servers being notified, no gossip protocol between resolvers. DNS is pull-based. Your authoritative nameservers hold the current answer, they hand it out when asked, and they hand out the new value from the moment you save. Zero seconds.

What takes time is the layer in between. Every recursive resolver that already asked keeps the answer for a while, because that is the entire point of DNS: about 5 to 10 lookups per page load, billions of clients, and a root zone that would melt if nobody cached. So the resolver at your ISP, at your employer, at Cloudflare and Google, each sit on their own copy with their own countdown. Those countdowns start at different moments. That is why two DNS checker sites disagree, and it is why the change looks like it is “spreading”.

The practical consequence is worth internalising before the next migration: you cannot make a change go faster once you have made it. You can only make it fast in advance, by publishing a short TTL before you touch anything. Everything else is waiting.

What a TTL actually does

The TTL is a number of seconds attached to every record in the answer. It tells a resolver how long it may reuse the answer without asking again. It is not a timer on your side and not a promise about anything else.

A detail most people miss: the TTL a resolver reports back to you is the remaining lifetime, not the configured value. Query the same name twice against 1.1.1.1 a few seconds apart and watch the number shrink. When it reaches zero the cache entry is dropped and the next query goes back to your authoritative server. That countdown is the single most useful debugging signal in DNS, and it costs one dig to read.

TTLWorst case after a changeSensible for
60 to 3001 to 5 minutesfailover, active migrations, records you are testing
36001 hournormal A, AAAA and CNAME records
8640024 hoursMX, TXT, anything that never moves
17280048 hourswhat registries publish for your NS records, and you don’t control it

One quirk worth knowing because it produces bizarre behaviour: RFC 2181 says the TTL is a 31-bit unsigned value, and any value with the top bit set has to be treated as zero. Some old control panels happily accept a negative number in the TTL field. The result is a record that is never cached at all, and a nameserver that suddenly serves every lookup on the planet for that name.

The 48 hours you actually wait for

The 48-hour warning your registrar shows is not marketing padding, it is just attached to the wrong thing. It applies to nameserver changes, not to record changes, and the TTL involved is one you cannot edit.

Your domain is delegated to your nameservers by NS records in the TLD zone, and the registry sets their TTL. Ask a gTLD server directly and you can read it off:

QueryAnswer
dig @a.gtld-servers.net github.com NS8 NS records, TTL 172800

172800 seconds is 48 hours, and that is where the number comes from. Verisign publishes the .com delegation with that TTL, the glue records too, and no setting in your DNS provider changes it. Point your domain at new nameservers and a resolver that cached the old delegation five minutes earlier will keep asking the old provider for up to two more days. If the old provider still answers with the old zone, that resolver is served stale data the entire time, and it will look completely healthy while doing it.

So the rule that follows from this: never delete the zone at the old provider on switch day. Keep it running, with the records updated to the new targets if you can, for at least 48 hours after the delegation change. Deleting it early is what turns a quiet migration into an outage for a slice of your users, and there is no way to tell which slice.

Negative caching, or why checking too early hurts

“This name does not exist” gets cached as well. RFC 2308 from March 1998 defines it, and the lifetime does not come from the record you were looking for (there isn’t one), it comes from the SOA record of the zone. The resolver takes the smaller of the SOA MINIMUM field and the TTL of the SOA record itself, and caches the NXDOMAIN for that long.

Which is why the most common self-inflicted DNS problem is impatience. You create api.example.com, but two minutes earlier you had already typed it into a browser to “see if it works yet”. That lookup returned NXDOMAIN, your resolver filed it, and now the record exists but your resolver will insist it doesn’t until the negative entry expires. People then create the record a second time, restart things, and blame the provider.

The real numbers for the two providers most projects use, read from their SOA records:

ProviderSOA (abbreviated)NXDOMAIN cached for
AWS Route 53TTL 900, MINIMUM 8640015 minutes
CloudflareTTL 1800, MINIMUM 180030 minutes

RFC 2308 section 5 also notes that the protocol technically allows negative caching for up to 68 years, recommends one to three hours as a default, and warns that values above a day “have been found to be problematic”. Resolver authors took that seriously, so in practice you are looking at minutes. Still long enough to make you doubt your own zone file.

Same trap, different flavour: DKIM keys. Publish the selector TXT record first, verify it resolves, and only then flip the signing switch at your mail provider. If your provider checks the selector before it exists, the NXDOMAIN gets cached and the verification fails for the next half hour. Our guide to SPF, DKIM and DMARC covers the rest of that ordering problem.

The caches nobody counts

Even with every resolver up to date, your own machine can lie to you for a while. There are more layers than most people expect, and they do not share state.

  • The operating system. macOS caches in mDNSResponder, and the flush is sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder. Windows caches in the DNS Client service, cleared with ipconfig /flushdns, and it enforces its own ceiling: MaxCacheTtl under HKLM\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters defaults to 86400 seconds, so nothing is cached longer than a day no matter what your zone says.
  • The browser. Chrome keeps its own host cache, independent of the OS. You clear it on chrome://net-internals/#dns, and that is the part people find. What they miss is the socket pool on the #sockets tab: an already established connection to the old IP keeps getting reused, so the page still loads from the old server even after the DNS cache is empty. Flush both.
  • The router. Consumer routers usually run a small forwarding resolver, and a fair number of them ignore TTLs entirely and keep entries until reboot. If one device in the house sees the new IP and another does not, this is your suspect.
  • The application. The JVM is the classic offender: it caches successful lookups in-process, historically forever when a security manager was installed, and it is controlled by networkaddress.cache.ttl rather than by DNS. Long-lived connection pools in any language have the same effect for as long as the connection stays open.

Two public resolvers let you clear a single name on demand, which is the closest thing to a manual purge that exists: Cloudflare has a purge-cache page on one.one.one.one, Google Public DNS has one at dns.google/cache. Both take one hostname and one record type at a time. Useful when your own testing poisoned a name, useless for the millions of resolvers you do not operate.

The TTL playbook for a migration

Everything above collapses into a boring sequence. We have run it often enough to trust it more than any status page.

  1. At least one old-TTL before the move, lower the TTL on every record you will touch to 300. If the records currently sit at 86400, that means a full day ahead, because resolvers keep the old TTL until it expires. Lowering it an hour before the switch does nothing for anybody who cached it yesterday.
  2. Build the complete new zone first and query the new nameservers directly with dig @ns1.newprovider.com example.com A. Every record, including MX, SPF, DKIM and DMARC. A delegation switch takes the whole zone with it, so a forgotten TXT record breaks mail at the same moment as everything else.
  3. Switch, then leave the old zone alive. 48 hours minimum for a nameserver change, longer if it costs you nothing.
  4. Watch the old server’s logs, not a checker site. When requests to the old IP go to zero, the migration is genuinely done. That signal is real, the green pins on a map are guesswork.
  5. Put the TTL back up to 3600 once traffic looks right. Leaving everything at 300 forever adds a lookup to a large share of connections and makes your DNS provider a hard dependency of every page view.

If the migration also changes URLs, do the redirects in the same window and get them right the first time, because a wrong 301 sticks in browser caches far longer than any DNS record. We wrote up that failure mode in 301 vs 302 redirects.

Debugging a change that hasn’t landed

Three commands answer almost every “DNS isn’t working” question, in this order.

First, ask the authoritative server directly: dig @ns1.yourprovider.com example.com A. If the answer is wrong here, the problem is your zone and no amount of waiting fixes it. Second, ask a public resolver: dig example.com A @1.1.1.1, and read the TTL as a countdown. A value of 2843 means that resolver cached the answer 757 seconds ago with a TTL of 3600, and will refresh it in 47 minutes. Third, ask your own resolver with plain dig example.com A and compare. Different answers between step two and step three mean the record is fine and something local is stale.

Add dig +trace example.com when the delegation itself is in question. It walks from the root down and shows you which nameservers the TLD currently hands out, which is exactly the information that a checker site hides behind a map. And check dig example.com NS against both the parent and your own zone: when those two sets disagree, you are in the middle of a delegation change that has not finished, and the 48-hour clock is the answer to “how long”.

TTL and propagation questions

How long does DNS propagation take?

For a normal record change it takes exactly as long as the TTL you had set before the change, because that is how long resolvers keep the old answer. Change an A record with a TTL of 3600 and the worst case is one hour, not 48. The 48-hour figure comes from nameserver changes: the NS records that delegate your domain live in the TLD zone, and registries like Verisign hand them out with a TTL of 172800 seconds, which is two days.

Why do DNS checker sites show different IP addresses?

Because each of those probes queries a different resolver, and every resolver has its own cache with its own countdown. A resolver that looked up your record 10 minutes before you changed it will keep serving the old answer until its copy expires; one that had nothing cached fetches the new answer immediately. The map with red and green pins is a picture of cache states, not of a change travelling across the world.

Can I speed up DNS propagation?

Not after the fact, only before it. Once a resolver has cached a record, you cannot reach into it, and the only lever you had was the TTL you published beforehand. The two public resolvers that let you clear single names are Cloudflare (the purge-cache page on one.one.one.one) and Google Public DNS (dns.google/cache); everything else expires on its own schedule. Lowering the TTL after the change helps nobody, because the resolvers already hold a copy with the old value.

What is a good TTL for DNS records?

For stable records, 3600 seconds (one hour) is a sensible default, with 300 seconds while you are actively changing something. Very low TTLs everywhere cost you: every expiry is another round trip before the connection can start, and it makes your zone the single point of failure for every page load. The pattern we use is boring but works: drop to 300 a day before a migration, run the migration, then put it back to 3600 once traffic looks right.

Why does my site still show the old server after the DNS change?

Usually because something between you and the authoritative server still holds the old answer: your operating system cache, your browser, your router, or your ISP resolver. Check with dig or nslookup against 1.1.1.1 and against your own resolver and compare. If the public resolver already returns the new address and only your machine does not, the record is fine and you are looking at a client cache, which flushes in seconds.

Does clearing the browser cache fix DNS problems?

Clearing the normal browser cache does not touch DNS, because browsers keep a separate host cache. In Chrome you clear it on the chrome://net-internals/#dns page, and you often also have to flush the socket pools on the neighbouring #sockets page, since an already open connection to the old IP keeps being reused. On macOS the OS-level equivalent is flushing the directory service cache and restarting mDNSResponder.

What is negative caching in DNS?

Negative caching is the rule that a "this name does not exist" answer gets cached too, defined in RFC 2308 from March 1998. The lifetime comes from the SOA record of the zone: resolvers use the smaller of the SOA MINIMUM field and the TTL of the SOA record itself. That is why looking up a hostname before you create it is actively harmful, since the NXDOMAIN you just caused sticks around for minutes after the record exists.

Will I lose emails when I change nameservers?

You can, if the new zone is missing MX records or the old provider stops answering before the delegation TTL has expired. Sending servers keep the old MX answer for its TTL, and a message that arrives at a mail server which no longer accepts it gets deferred and retried for a few days, so most of it survives. The safe order is to build the complete zone at the new provider first (MX, SPF, DKIM, DMARC included), verify it by querying the new nameservers directly, and only then switch the delegation at the registrar.