TTL Too High Makes DNS Changes Slow

You changed DNS but it takes 24+ hours to propagate. Lowering TTL before changes makes propagation predictable.

You repointed an A record from old hosting to new hosting. The new server is ready. You can curl the new IP and see the new site. But half your users still see the old site, your email logs show traffic hitting the old IP, and your phone (on cellular) sees the new site while your laptop (on home Wi-Fi) sees the old one. Nothing is broken — you’re watching cached DNS expire at different rates around the world, because the TTL on your record was set high before the change.

This is the single biggest cause of “DNS doesn’t propagate” complaints, and it is preventable. The fix takes 30 seconds, but only if you do it 24 hours before the change, not after.

How TTL actually controls propagation

TTL (Time To Live) is a number in seconds that the authoritative DNS server attaches to every answer. Every recursive resolver between you and the user (their ISP, their corporate firewall, Cloudflare 1.1.1.1, Google 8.8.8.8) caches the answer for at most that long.

  • TTL 300 = answers expire after 5 minutes → next query goes back to authoritative → users see the new value within 5 minutes.
  • TTL 3600 = up to 1 hour.
  • TTL 86400 = up to 24 hours.
  • TTL 172800 (2 days) = up to 48 hours. Common registrar default.

The TTL of the current record is what governs how long the old value stays cached. Changing TTL at the same time as changing the value does nothing for the existing caches — they already grabbed the value and the TTL, and they’ll keep both until expiry.

How to identify which case you’re in

Case 1: You changed the record today and it still hasn’t fully propagated

The most common case. You changed both the value and the TTL today. The old caches still have the old TTL counting down.

How to spot it:

# Query authoritative directly — shows the new value immediately
dig yourdomain.com @ns1.your-dns-provider.com +short

# Query public resolvers — some show new, some show old
dig yourdomain.com @8.8.8.8 +short
dig yourdomain.com @1.1.1.1 +short
dig yourdomain.com @9.9.9.9 +short

# Check the cached TTL countdown
dig yourdomain.com @8.8.8.8
# Look at the TTL column in the ANSWER SECTION — that's seconds remaining

If dig against the authoritative server returns the new value but public resolvers return old, the old TTL is still running.

Fix: there isn’t one. Wait. The next time, lower TTL 24 hours before.

Case 2: DNS provider is silently capping or ignoring your TTL

Some registrar-as-DNS combos (older Namecheap shared DNS, some GoDaddy plans, free Bluehost DNS) cap TTL at 3600 or 86400 regardless of what you enter, or display 300 in the UI while serving 7200 in the actual response.

How to spot it:

# What does the authoritative actually say?
dig yourdomain.com @<authoritative-ns> | grep -E "^yourdomain"
# The middle number is TTL in seconds. Compare to UI.

If UI shows 300 but dig shows 3600+, the provider is lying.

Fix: switch DNS providers to one that respects TTL (Cloudflare, Route 53, Google Cloud DNS, deSEC). Or accept the cap and plan changes 24h ahead.

Case 3: Negative cache (NXDOMAIN TTL) makes new subdomains slow to appear

You added blog.example.com for the first time. It still doesn’t resolve. This isn’t your A record’s TTL — it’s the SOA minimum TTL that controls how long resolvers cache an NXDOMAIN response.

How to spot it:

dig SOA yourdomain.com +short
# Output: ns1... admin... serial refresh retry expire minimum
# The last number is the negative-cache TTL.
# If it's 86400, an NXDOMAIN is cached for up to a day.

Fix: lower the SOA minimum field (your DNS provider’s UI may call it “Negative TTL” or “NXDOMAIN TTL”). For Cloudflare and Route 53 the default is already 300; for older zones it can be 86400.

Case 4: CDN / proxy layer in front of DNS

Cloudflare’s proxy mode (orange cloud) sends a tiny TTL on the public-facing record but ignores your origin TTL for cache headers. Vercel and Netlify Edge cache their own.

How to spot it: dig yourdomain.com +short returns Cloudflare IPs (104.x.x.x) not your origin. The TTL on those is short, but Cloudflare’s internal origin pull is governed by their own rules.

Fix: for DNS-layer propagation, TTL is moot once Cloudflare is in front — they handle the switch in ~30 seconds via their own edge. If you mean “users still see the old site,” that’s HTTP cache, not DNS — purge Cloudflare cache from the dashboard.

Shortest fix path (for the next change)

The fix is procedural, not reactive. Run this 24 hours before any planned DNS change:

  1. 24 hours before: at the authoritative DNS provider, change TTL on every record you plan to touch from its current value (often 3600 or 86400) to 300. Don’t change the value yet. Save.

  2. Wait for the old TTL to expire. If the old TTL was 3600, wait at least 1 hour; if 86400, wait 24 hours. After this point, every cache will refresh within 5 minutes.

  3. Make the actual change (value + TTL still 300).

  4. Verify:

    for resolver in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
      echo "@$resolver: $(dig yourdomain.com @$resolver +short)"
    done

    All should show the new value within 5 minutes.

  5. The next day: raise TTL back to 3600 or higher to reduce DNS query load and improve cache hit rate.

How to check what TTL is actually in effect right now

# Authoritative TTL (what the DNS provider sends)
dig yourdomain.com @<authoritative-ns> | awk '$1=="yourdomain.com." {print $2; exit}'

# Cached TTL countdown at a public resolver (changes on each query)
dig yourdomain.com @8.8.8.8 | awk '$1=="yourdomain.com." {print $2; exit}'

# Repeat the public query in 60s — it should decrement by ~60
sleep 60
dig yourdomain.com @8.8.8.8 | awk '$1=="yourdomain.com." {print $2; exit}'

If the cached countdown jumps back up to the full TTL, the resolver fetched fresh — the old answer expired and the new one is now cached. From this moment on, every user on that resolver sees the new value.

Prevention

  • Treat TTL like a knob you turn down before maintenance. Set a calendar reminder: “T-24h: lower TTL to 300.” Then change. Then “T+24h: raise back to 3600.”
  • For records you change frequently (preview environments, staging, A/B test endpoints), leave TTL at 300 permanently. The query-load cost is trivial.
  • For records you never change (root MX, SPF TXT, DKIM TXT), leave TTL at 86400. Higher cache hit rate, fewer outages if your DNS provider has a brief outage.
  • Don’t change TTL and the record value in the same operation: it doesn’t help. The damage was the previous TTL on the previous value.
  • Pick a DNS provider that respects TTL. Cloudflare, Route 53, Google Cloud DNS, NS1, DNSimple all honor it precisely. Some cheap registrar bundled DNS does not.

When this isn’t on you

  • The user’s ISP has its own caching layer that ignores authoritative TTL and caches for fixed periods (rare, but documented at Comcast and some Asian ISPs).
  • A corporate firewall / WAF caches DNS independently.
  • A browser-level secure DNS (DoH) profile caches separately from the OS.
  • The user has set their /etc/hosts file manually and is no longer using DNS at all.

These are all out of your control. The right answer is to communicate the expected propagation window and move on.

FAQ

Q: What’s a sane long-term TTL for production records? A: 3600 (1 hour) is the sweet spot for records you might change in an emergency. 86400 (1 day) for records you’ll never touch. 300 (5 min) only during planned changes or for endpoints you change weekly.

Q: Does lowering TTL hurt performance? A: A little. Each cache miss adds one DNS round-trip (~20ms) for the first user in that resolver’s region. With TTL 300, a busy resolver still hits cache 99%+ of the time, so the impact is negligible. With TTL 3600, it’s even less.

Q: Cloudflare proxy says TTL is auto. What does that mean? A: When a record is proxied (orange cloud), Cloudflare returns its own IPs with a fixed short TTL (~5 minutes) to the public. Your “auto” setting is irrelevant for public propagation, but Cloudflare’s own edge updates within ~30 seconds when you change the origin. For DNS-only (gray cloud) records, the TTL you set is what’s served.

Q: Can I force resolvers to flush their cache? A: Generally no. You can flush your own machine, and you can ask users to. Public resolvers will not flush on your request. The exceptions: Google offers dns.google/cache to clear a specific name from 8.8.8.8; Cloudflare has a similar form for 1.1.1.1. Useful for the post-mortem 1% who still see stale.

Q: I lowered TTL but the change is still slow. A: You lowered TTL today and changed the record today. The old TTL is what governed the cache for the old answer. Wait at least the duration of the old TTL — if it was 86400, that’s 24 hours — for caches to flush. Then future changes will be fast.

Tags: #Domain #DNS #SSL #Troubleshooting #TTL #DNS propagation