← Back to Blog

DNS Propagation: Why Your Changes Aren't Visible and How to Fix It

DNS · June 11, 2026 · 7 min read

DNS changes take time to propagate through caches across the internet. Learn what TTL really controls, how to check propagation status, and what to do when your changes refuse to appear.

Technical cover image for DNS Propagation: Why Your Changes Aren't Visible and How to Fix It

You Changed Your DNS. Now What?

You update an A record and hit save. Five minutes later, a coworker says it still resolves to the old IP. Ten minutes pass. Still nothing. This is DNS propagation — or more accurately, DNS caching — and it confuses even experienced sysadmins.

Propagation is a misleading term. DNS changes do not "propagate outward" from an origin. Every resolver on the internet caches records for a duration specified by the TTL, and they will not ask for fresh data until that timer expires. Understanding this makes the difference between fixing a problem in 5 minutes and staring at a screen waiting for magic to happen.

How DNS Caching Actually Works

When a resolver queries an authoritative nameserver, it receives a TTL alongside each record. The resolver stores the record locally and serves it from cache until the TTL expires. Only then does it make another upstream query.

There are multiple layers of caching:

Browser cache (Chrome/Firefox DNS cache)
    |
Local OS stub resolver cache (systemd-resolved, nscd)
    |
Local network resolver (home router, ISP recursive resolver)
    |
ISP or public resolver cache (1.1.1.1, 8.8.8.8, ISP resolvers)
    |
Authoritative nameserver

Each layer independently obeys the TTL it received. A record with TTL 3600 (one hour) may take a full hour to expire from every cache in the chain. If your browser cached it for 3600 seconds, your ISP for 3600, and the public resolver for 3600 — you could be waiting up to an hour even after your own local cache clears.

Use the OpsCheck DNS Propagation Checker to see what different resolvers around the world are returning right now. You will often see a mix: some resolvers serving old records, some serving new ones, and some returning NXDOMAIN for newly created records.

TTL Strategy: Plan Your Changes

The single most important habit for DNS management is lowering TTLs before making changes. If your A record has a TTL of 86400 (24 hours) and you change the IP without lowering it first, you commit to up to 24 hours of stale data being served.

The workflow:

# Step 1: Days before the change — lower the TTL
# Change from 86400 to 300 (5 minutes)
$ dig example.com A +short
93.184.215.14

$ dig example.com A | grep TTL
example.com.    86400    IN    A    93.184.215.14

# Wait for old TTL to expire (24 hours), then:

# Step 2: Make the actual DNS change
# A record now points to 192.0.2.10 with TTL 300

# Step 3: Verify with multiple resolvers
$ dig @1.1.1.1 example.com A +short
$ dig @8.8.8.8 example.com A +short
$ dig @9.9.9.9 example.com A +short

# Step 4: Confirm propagation, then raise TTL back to 86400

This pattern is mandatory for production migrations. Skip it, and you will have users hitting old servers for hours — or worse, some users hitting new servers and others hitting old ones simultaneously.

Checking Propagation from the Command Line

You have several tools available without leaving the terminal. The simplest is querying multiple public resolvers:

# Check against four major public resolvers
for ns in 1.1.1.1 8.8.8.8 9.9.9.9 208.67.222.222; do
    echo "=== $ns ==="
    dig @@$ns example.com A +short
done

For a broader view, the OpsCheck DNS Propagation Checker queries dozens of geographically distributed resolvers and shows you which ones have picked up the change and which have not. This is far more useful than the single-resolver output from dig alone.

You can also check the authoritative nameserver directly to confirm your change was saved:

# Find the authoritative NS for the domain
$ dig example.com NS +short
ns1.example.com.

# Query it directly — bypass all caching
$ dig @ns1.example.com example.com A +short
93.184.215.14

If the authoritative server returns the new value but public resolvers return the old one, the issue is caching. Wait for TTL expiration. If the authoritative server itself returns the old value, your change did not take effect — check the zone file or control panel.

The Negative Cache Problem

If you create a brand new subdomain that previously did not exist, resolvers cached the NXDOMAIN (non-existent domain) response. Negative caching is governed by the SOA record's MINIMUM field or the negative TTL, whichever is configured.

# Check the negative TTL (last field in SOA)
$ dig example.com SOA +short
ns1.example.com. admin.example.com. 2026061101 7200 3600 1209600 300
#                                                            ^^^
#                                       Negative cache TTL: 300 seconds

Even after you create the new record, resolvers that previously queried for it will keep returning NXDOMAIN until their negative cache expires. This is why a freshly created subdomain sometimes appears "down" for the first few minutes.

The fix: if you know you will create new subdomains, lower the SOA minimum TTL in advance. Or, test against a resolver that has never queried for that subdomain before (Cloudflare's 1.1.1.1 is a good choice since it handles millions of unique names and likely does not have your subdomain cached).

DNSSEC and Propagation Delays

If your domain is DNSSEC-signed, you have an additional caching layer to worry about. DNSSEC validation failures occur when a resolver's cached RRSIG signatures do not match the new record data. This produces a SERVFAIL response instead of stale data — which is both better (no silent misdirection) and worse (complete outage for validating resolvers).

Always sign the zone after making changes if your provider does not do it automatically. Unsigned changes on a signed zone break everything for users behind validating resolvers.

# Check if a domain uses DNSSEC
$ dig example.com +dnssec | grep -E "RRSIG|flags.*ad"

# Verify DNSSEC chain of trust
$ dig example.com +dnssec +trace | grep -E "RRSIG|DS"

Real-World Scenario: The Migration That Broke at Midnight

A team migrates their application from one hosting provider to another at 10 PM on a Saturday. They update the A record for api.example.com from 198.51.100.10 to 203.0.113.50. They test from their office network, everything works, and they call it done.

By midnight, users start reporting failures. The old IP still shows up for some users. Others get connection timeouts. The team checks their DNS provider's control panel — it shows the new IP. They run dig from their office — it shows the new IP. What happened?

The TTL was 86400. Their office resolver happened to have an expired cache and fetched the new record quickly. But users on different ISPs still had the old record cached. Some ISPs had intermediate resolvers with aggressive caching that ignored even the TTL entirely. Meanwhile, the old server was already shut down, so users who still resolved to it got nothing.

The fix after the fact:

# The old server needs to stay up as a reverse proxy
# forwarding traffic to the new server during the TTL window.

# Or, set up iptables forwarding on the old IP:
iptables -t nat -A PREROUTING -p tcp --dport 443 \
    -j DNAT --to-destination 203.0.113.50:443
iptables -t nat -A POSTROUTING -j MASQUERADE

The correct approach: lower the TTL to 300 seconds at least 24 hours before the migration. After the old TTL expires from all caches, make the IP change. Monitor with the OpsCheck DNS Propagation Checker until all resolvers show the new address. Only then decommission the old server. Leave it running for at least 2x the original TTL as a safety margin.

Flushing Caches: What You Can and Cannot Do

You can flush local caches. You cannot flush ISP or public resolver caches — no amount of asking will make Google flush 8.8.8.8 for you.

# macOS
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder

# Linux with systemd-resolved
sudo systemd-resolve --flush-caches

# Linux with nscd
sudo systemctl restart nscd

# Windows
ipconfig /flushdns

# Chrome internal DNS cache
# Navigate to chrome://net-internals/#dns and click "Clear host cache"

# Firefox: about:networking#dns -> "Clear DNS Cache"

After flushing your local cache, run a quick verification with OpsCheck DNS Lookup to confirm the resolver is returning the expected records. If not, the authoritative side still has the old data or your change simply needs more time.

DNS propagation is not magic. It is TTL math. Respect the TTL, test from multiple vantage points, and always leave old infrastructure running through the transition window. Do that, and your next DNS change will be unremarkable — which is exactly what you want.