You change the A record forapi.example.comfrom203.0.113.10to203.0.113.20`. Your browser shows the new IP. The deployment dashboard says green.
Then the Slack messages start rolling in:
"API is down from Singapore."
"Connection refused from Frankfurt."
"Works fine here in Virginia."
This is DNS propagation. It is not a single number. It's a probability distribution — shaped by your TTL, the cache policies of 8 major resolver populations, and the geographic topology of the DNS hierarchy itself.
The user on Google DNS sees the change in 60 seconds. The user on Deutsche Telekom might wait 24 hours. Both readings are correct from their vantage point.
The Hidden Architecture Nobody Explains
DNS is not a push protocol. When you update a record at your authoritative nameserver, it doesn't notify anyone. It waits. Resolvers come to it when their cached copy expires. The time between "change made" and "every resolver has the new answer" is your propagation window — and it's determined entirely by cache expiration, not network physics.
The Four-Step Lifecycle of a DNS Change
| Step | What Happens | Timer |
|---|---|---|
| 1 | You update the zone file and increment SOA serial | t=0 |
| 2 | A resolver cold-queries your authoritative NS, gets the new record, starts its TTL countdown | t + RTT |
| 3 | While TTL ticks, all users behind that resolver get the cached answer | TTL window |
| 4 | TTL expires, resolver re-queries, gets the new record | t + RTT + TTL |
The key insight: each resolver's countdown started when it last cached the record — not when you made the change. If a resolver cached the old record 30 seconds before your update with a 3600s TTL, it will serve the old value for 59 minutes and 30 seconds after your change.
The 8 Resolver Populations
Tier 1: Strict TTL Honor (Fastest)
Google Public DNS — 8.8.8.8
- Walks the DNS hierarchy from root to authoritative for every cold query. No upstream forwarding. No minimum TTL override.
- Propagation: TTL + 0–60s. At 300s TTL: 5–6 minutes.
- Market share: ~10% of global DNS. Default on many Android OEM builds.
Cloudflare 1.1.1.1 — 1.1.1.1
- 330+ edge locations. Cache is per-edge, not global — Mumbai and London may see the record expire at slightly different times.
- Propagation: TTL + 0–90s.
- WARP catch: Cloudflare WARP users layer an additional cache at the egress point. Adds 30–60s delay vs native 1.1.1.1.
Tier 2: Mostly Honoring (Slight Lag)
Quad9 — 9.9.9.9
- Honors TTL but enforces a 30s minimum. Every query passes through IBM X-Force + 18 threat-intelligence feeds; filtering adds 5–50ms to cold queries but doesn't affect cached answers.
- ⚠️ DNSSEC landmine: Quad9 validates DNSSEC by default. Broken DNSSEC → SERVFAIL → cached for the negative TTL. Frequently misdiagnosed as "propagation failure."
OpenDNS / Cisco Umbrella — 208.67.222.222
- Honors TTL with 1–3 min processing overhead from content filtering. Enterprise Umbrella users may have admin-configured cache overrides.
- NXDOMAIN handling: free tier replaces NXDOMAIN with a search page. Irrelevant to propagation but confusing during testing.
Tier 3: ISP Resolvers — The Wild West
Comcast / Xfinity — 75.75.75.75
- Minimum TTL: 300s for A/AAAA. Regional cache clusters — East Coast ≠ West Coast.
- Propagation: max(your TTL, 300s) + 0–15 min.
- ~30 million subscribers. Largest single ISP resolver population in the US.
BT / EE (UK)
- Minimum TTL: 900s for A/AAAA. Independent regional clusters.
- Propagation: max(your TTL, 900s) + 0–10 min.
Deutsche Telekom — the reason "48 hours" exists
- Minimum TTL: 3,600s (1 hour) for A/AAAA. The most aggressive override among major ISPs.
- Three-tier hierarchical cache: edge → regional → central. Each tier caches independently. All three must expire sequentially before the change propagates.
- Propagation: 1–24 hours for A records. NS changes: 48+ hours.
- 45 million subscribers. This single ISP is why "DNS takes 48 hours" persists as industry lore — for their users, it genuinely can.
General ISP defaults — the catch-all model
- Most Tier 2/3 ISPs run BIND or Unbound with default configs. BIND default min-TTL: 300s. Unbound: no minimum, but 86400s maximum. Many ISPs customize upward.
- Safe assumption: ISP resolvers enforce 300–900s min for A/AAAA, 3600s for MX/NS, 600–3600s for negative caching.
The Pre-Warming Playbook
The difference between a 5-minute cutover and a 48-hour outage for half your users:
| Day | Action | Why |
|---|---|---|
| T–1 day | Lower TTL to 60–300s. Wait ≥ old TTL duration. | Expire the old long cache everywhere before the change. |
| T=0 | Make the DNS change. | Every resolver now has a short stale window, not a long one. |
| T+1 hour | Verify propagation across all 4 public resolvers. | Confirm the change is live. |
| T+1 day | Restore original TTL. | Operational TTL back to normal; short TTL already expired. |
The logic: you're not fighting stale caches — you expired them before the battle. A 60s TTL means 60s propagation on Google DNS and Cloudflare. 300s on Comcast (their minimum). 3600s on Deutsche Telekom (their minimum). Pre-warming eliminates the old-cache variable; it cannot override ISP minimum TTL policies.
When pre-warming fails: NS record changes. Parent zone NS records have registry-level TTLs (.com = 2 days, set by Verisign). No amount of pre-warming your own zone accelerates registry TTLs. Nameserver migrations are inherently 24–48 hour affairs.
Quick Propagation Check
`bash
Test each major resolver
dig +short A example.com @8.8.8.8 # Google
dig +short A example.com @1.1.1.1 # Cloudflare
dig +short A example.com @9.9.9.9 # Quad9
dig +short A example.com @208.67.222.222 # OpenDNS
Google DNS-over-HTTPS (machine-readable)
curl -s "https://dns.google/resolve?name=example.com&type=A" | jq '.Answer[] | {name, data}'
`
Golden rule: if Google DNS returns the new IP but your ISP doesn't — it's your ISP's cache policy, not your DNS configuration. Don't touch the zone file. Wait.
Try the interactive propagation modeler at jslet.com/dns-propagation — plug in your TTL, record type, and see per-resolver estimates across all 8 populations. 100% client-side.
`
Top comments (0)