DNS does not propagate
Nothing is pushed anywhere when you change a record. Your authoritative nameservers start giving the new answer the moment you save. Everyone else, meaning every recursive resolver in the world that has recently looked up that name, keeps the old answer in cache until the time-to-live it was given runs out. Then it asks again and gets the new value. "Propagation" is just the sum of all those caches expiring at different times.
So the maximum delay for a record change is the old record's TTL. If the A record had a TTL of 3600, every resolver that cached it will have the new value within an hour. If it was 86400, a day. The 48 hours figure comes from the days when a day-long TTL was the default and people added a safety margin.
What actually adds delay
| Factor | Typical delay | What to do |
|---|---|---|
| TTL of the record you changed | Whatever it was set to: 300 s to 86400 s | Lower it to 300 a day or two before the change, so the old low TTL is what gets cached. |
| Negative caching | SOA minimum TTL, often 3600 or more | If the name did not exist before, resolvers cache the NXDOMAIN. Create the record early, even with a placeholder value. |
| Changing nameservers (NS at the registrar) | Up to the TLD's TTL on the NS records, typically 2 days for .com | Set up the zone completely at the new provider before switching, so either set of servers gives the right answer. |
| Changing a DS record (DNSSEC) | TLD DS TTL, typically 1 day | Plan key rollovers; never remove the old key before the new DS has aged in. |
| Resolvers that ignore TTLs | Minutes to hours beyond the TTL | Some ISPs and corporate resolvers enforce a minimum TTL or serve stale on error. Not much you can do; test from several networks. |
| Browser and OS caches | Seconds to minutes | Chrome caches for about a minute; Windows for the TTL. Restart the browser or flush (ipconfig /flushdns, sudo dscacheutil -flushcache). |
| CDN or application caches | Varies | Not DNS at all, but often blamed on it. Check the HTTP response actually comes from the new origin. |
Planning a cutover
- Two days before: lower the TTL on every record you will change to 300 (five minutes). Do not change the values yet. Wait for the old, long TTL to expire everywhere; that is the last time you will have to wait for it.
- Day of: change the values. Within five minutes, every resolver that re-asks gets the new answer.
- Check from several resolvers, not just your own. Your resolver may have the old value cached for another four minutes while the rest of the world already sees the new one, or the other way round.
- A day after: raise the TTL back to something sensible (3600 is a reasonable default; 300 forever just adds load and latency).
For a nameserver change, build the full zone at the new provider first and verify it by querying the new servers directly. Only then update the NS records at the registrar. During the two-day overlap both providers answer, and as long as they agree nobody notices.
How to check whether a change has propagated
Query several independent resolvers and compare. The DNS lookup tool lets you pick Cloudflare, Google or Quad9 for the same name, and shows the TTL each one returns. A resolver serving the old value shows a TTL counting down; that number is exactly how many seconds until it re-asks. A resolver serving the new value with the full TTL has already refreshed.
To see the source of truth, query an authoritative server directly. Look up the NS records, then enter one of those servers' IPs as the resolver. If the authoritative answer is wrong, propagation is not your problem.
dig example.com A @1.1.1.1 +noall +answer # what Cloudflare has cached dig example.com A @8.8.8.8 +noall +answer # what Google has dig example.com NS +short # who is authoritative dig example.com A @ns1.example.net +noall +answer # the truth
Things that look like propagation but are not
- The record was changed in the wrong place. Two zones (an old provider and a new one) and the registrar still points at the old one.
- A CNAME in the middle with its own long TTL. You changed the A record at the end of the chain, but the CNAME's target was cached separately.
- Split horizon: your office resolver serves an internal zone with different values from the public one.
- The application caches DNS. Java's default is to cache forever in some configurations; connection pools hold sockets open to the old address indefinitely. Restart the process.
- Happy Eyeballs: you changed the A record but not the AAAA, and dual-stack clients are still using IPv6 to the old host.
Sensible TTLs
300 for anything you expect to change during an incident (load balancer addresses, failover records). 3600 for ordinary A, AAAA and CNAME records. 86400 for things that essentially never change: NS, MX, TXT verification records. Lower before a planned change, raise afterwards. The cost of a low TTL is more queries to your authoritative servers and a few extra milliseconds for visitors whose resolver has to re-ask; the cost of a high one is a long wait when something goes wrong.