DNS propagation: what actually happens after a change
DNS changes are not pushed anywhere: resolvers cache answers for the TTL. Why updates appear unevenly, why new records look missing and how to plan changes.
By Exmoor Software7 min read
You have probably been told to “allow up to 48 hours for DNS propagation”. The phrase suggests that a change travels across the Internet from server to server. It doesn’t. Nothing in DNS pushes your update to anyone. Usually within moments of your DNS provider saving the change, its authoritative servers answer with the new value. What you are waiting for is caches expiring — and once you know which caches and for how long, you can plan around them.
Authoritative and recursive servers
Two kinds of DNS servers are involved in every lookup:
- Authoritative servers hold your zone — they are the servers listed in your domain’s NS records, usually run by your DNS hosting provider. Their answers carry the AA (Authoritative Answer) flag (RFC 1035, section 4.1.1).
- Recursive resolvers do the looking up on behalf of clients: your ISP’s or company’s resolver, public services such as
8.8.8.8(Google) or1.1.1.1(Cloudflare), and the resolver a receiving mail server uses. They walk from the root to the TLD to your authoritative servers and cache what they learn.
On top of that, operating systems, browsers and some applications keep small caches of their own.
When a mail server checks your SPF record, it asks its own resolver. If that resolver fetched the record 20 minutes ago, it answers from its cache without contacting your servers at all.
TTL: how long an answer may be cached
Every record has a time to live, in seconds:
example.com. 3600 IN TXT "v=spf1 include:_spf.example.net -all"
RFC 1034, section 3.6 defines the TTL as a time limit on how long a record can be kept in a cache. A resolver that fetches this record may reuse it for up to an hour, counting down; only then does it ask your servers again.
Two consequences matter in practice:
- The TTL that counts is the old one. Resolvers that cached the record before your change will keep it for the TTL that was published then. Lowering the TTL together with the change doesn’t shorten the wait.
- The TTL is a maximum, not a promise. Resolvers may cap long TTLs and treat larger values as the cap (RFC 2181, section 8). Google Public DNS, for example, says in its FAQ that cached records are generally limited to six hours even if the actual TTL is longer. A resolver may also drop a record earlier, for example when its cache is full.
Some resolvers also implement serve-stale (RFC 8767): if none of your authoritative servers can be reached when a record expires, they may keep answering with the expired data instead of failing. That is one more reason not to switch off old DNS servers the moment you move away from them.
Negative caching: why a record you just created looks missing
Resolvers cache “this doesn’t exist” too. RFC 2308 says negative caching should no longer be seen as an optional part of a resolver, and distinguishes two cases:
- NXDOMAIN — the name doesn’t exist at all. It is cached for the name, regardless of record type.
- NODATA — the name exists but has no records of the requested type. It is cached for the name and that type.
A negative answer has no record to carry a TTL, so the authoritative server includes the zone’s SOA record. The negative TTL is the smaller of the SOA record’s own TTL and its MINIMUM field (RFC 2308, sections 3 and 5):
example.com. 3600 IN SOA ns1.example.net. hostmaster.example.com. (
2026102401 ; serial
7200 ; refresh
3600 ; retry
1209600 ; expire
1800 ) ; minimum: used for negative caching
Here a “doesn’t exist” answer may be cached for 1800 seconds. You can see it in a lookup of a name that isn’t there yet — status: NXDOMAIN and the SOA in the authority section, its TTL counting down:
$ dig TXT _dmarc.example.com
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 4711
;; AUTHORITY SECTION:
example.com. 1800 IN SOA ns1.example.net. hostmaster.example.com. 2026102401 7200 3600 1209600 1800
This is the classic trap with new records. You open a DMARC checker to see whether _dmarc.example.com exists, it doesn’t, you create it — and checks keep failing. The resolver remembers the earlier “no such name” until the negative TTL runs out. The same happens with a DKIM selector queried before the key was published, or an _mta-sts record that a sending server looked up shortly before you published it.
Why different resolvers show different answers
Seeing the old value on one resolver and the new one on another is normal during a change:
- Every cache filled at a different moment. A resolver that fetched the record a minute before your change keeps the old value for almost the whole TTL; one that fetched it just after already has the new one.
- One public resolver is many caches. Large public resolvers answer from many locations behind one anycast address, and each location keeps its own cache. Queries to
8.8.8.8can therefore return different values until every copy expires. - Your authoritative servers may disagree for a while. Secondary servers copy the zone from the primary when notified (RFC 1996) or when their SOA refresh timer fires (RFC 1034, section 4.3.5). Until then they serve the previous version — compare the SOA serial on each of them.
- Some answers depend on location. CDNs and geo-DNS services deliberately return different addresses in different places. That is rarely the case for mail-related records, but it explains differing A records for a website.
How to plan a DNS change
For a change to an existing record — new MX hosts, a changed SPF record, a DKIM key rotation:
- Look up the current TTL at the authoritative servers.
- Lower the TTL in advance — for example to 300 seconds — and wait at least as long as the old TTL, so every cache has picked up the short one. RFC 1034 recommends exactly this: reduce the TTL before an anticipated change and raise it again afterwards.
- Make the change and confirm the authoritative servers return the new value.
- Keep the old setup working for at least one TTL. Senders with a cached MX record still deliver to the old server; receivers with a cached DKIM key still verify against the old one.
- Raise the TTL again once the change has been confirmed.
For a new record, nothing has to be lowered: just avoid querying the name before it exists. If it has already been queried, wait for the negative TTL from the SOA, or ask the large public resolvers to drop their copy — Google Public DNS has a Flush Cache page and Cloudflare a Purge Cache page. Flushing your own computer’s cache (ipconfig /flushdns on Windows) only affects your computer.
Changing name servers works differently. The NS records that delegate your domain live in the parent zone (.com, .pl, …), with a TTL chosen by the registry, which you cannot lower. Until the old delegation expires from caches, some resolvers keep asking your old DNS provider. Copy the full zone to the new provider before switching, and keep the old provider serving the same, current zone for several days afterwards.
Checking a change
The DNS propagation checker compares the answers of several public resolvers with the answers of your domain’s authoritative servers. Enter the exact name you changed — example.com for MX or SPF, _dmarc.example.com for DMARC, selector1._domainkey.example.com for a DKIM key — and read the result from the authoritative side first:
| What you see | What it means | What to do |
|---|---|---|
| Authoritative servers return the old value or nothing | The change isn’t live: not saved, wrong zone, or edited at a provider that isn’t authoritative | Check the domain’s NS records and edit the zone where they point |
| Authoritative servers disagree with each other | A secondary hasn’t picked up the new zone version | Compare SOA serials; contact your DNS provider if it persists |
| Authoritative servers are right, some resolvers are old | Caching | Wait for the old TTL to run out |
| Authoritative servers are right, resolvers say the name doesn’t exist | Negative caching | Wait for the negative TTL, or flush the public resolvers |
Keep in mind that a checker sees each public resolver from where the checker runs. The resolver of a particular recipient’s mail server has its own cache that no outside tool can inspect.
From a terminal, ask an authoritative server directly — no recursion, and look for the aa flag — then compare with a public resolver:
dig +short NS example.com
dig +norecurse @ns1.example.net TXT _dmarc.example.com
dig @1.1.1.1 TXT _dmarc.example.com +noall +answer
On Windows:
Resolve-DnsName _dmarc.example.com -Type TXT -Server ns1.example.net
Resolve-DnsName _dmarc.example.com -Type TXT -Server 1.1.1.1
In dig output, the second column of a resolver’s answer is the remaining TTL: how long until that resolver asks again. For mail-specific checks after the records are live, use the MX lookup and the record checkers.
References
- RFC 1034 — Domain Names: Concepts and Facilities (section 3.6: TTL)
- RFC 1035 — Domain Names: Implementation and Specification
- RFC 2308 — Negative Caching of DNS Queries (DNS NCACHE)
- RFC 2181 — Clarifications to the DNS Specification (section 8: TTL)
- RFC 8767 — Serving Stale Data to Improve DNS Resiliency
- RFC 1996 — DNS NOTIFY
- Google Public DNS — Frequently asked questions