Before you start
- Access to change records at your DNS provider.
digon your machine, or any tool that can query a chosen resolver.- The old backend can keep serving for the length of the change.
Where the old answer lives
A resolver that cached the old record keeps serving it until its TTL runs out, and nothing you do at the authoritative server shortens that remainder. A name that did not exist when someone looked it up stays missing for the negative TTL. And client runtimes keep their own caches on top of the resolver: some honour the TTL, some do not.
The change plan
Step 1Write down the current TTL
The second column of the answer is the TTL in seconds as this resolver sees it. Ask the authoritative server directly to read the configured value instead of a remainder.
bash dig +noall +answer app.example.com A dig +noall +answer app.example.com A @ns1.example.comStep 2Read the negative TTL
Per RFC 2308, a resolver caches a missing name for the smaller of the SOA record's own TTL and its last field. If the change creates a new name, create it before anything looks it up.
bash dig +noall +answer example.com SOAStep 3Lower the TTL one old TTL ahead
Drop the TTL to something short, such as 60 seconds, then wait at least one full old TTL before the change. A cache that fetched the record before you lowered it holds it for the old TTL, so the new value only helps caches that refresh after the wait.
Step 4Change the record, keep the old backend
Point the record at the new address and leave the old backend running. Some clients will keep reaching it until every cache in front of them has expired.
Step 5Check from several resolvers
One resolver is one opinion. Compare the authoritative answer with at least three public resolvers, and decide in advance which answer means done.
bash for r in ns1.example.com 1.1.1.1 8.8.8.8 9.9.9.9; do echo "$r: $(dig +short app.example.com A @"$r")" doneStep 6Wait for the slowest client
The window after the change is the new TTL plus the longest client cache. Long lived processes and JVM services are the usual laggards: the JVM keeps its own cache controlled by the
networkaddress.cache.ttlsecurity property, and-1caches forever. Check each client in staging and plan for the slowest one.Step 7Raise the TTL, then retire the old backend
When the resolvers agree and the slowest client has moved, restore the long TTL. Retire the old backend last, after one more old TTL has passed.
A starting TTL policy
- General records such as web, API and mail hosts: an hour or more. RFC 9199 advises long TTLs for resilience and latency.
- NS and MX records: an hour to a day. A delegation change waits out the larger of the parent and child NS TTLs, so keep the old servers for that long.
- Health checked failover records: short, a minute or two, and only useful once the health check has fired.
- TTL 0: avoid it. It turns off caching entirely and moves the load onto your authoritative servers.
What to watch
- The authoritative answer and the answers from several resolvers, compared.
- The remaining TTL on a key record over time: a value that stays high after a change means a cache still holds the old copy.
- The NXDOMAIN rate for names that should exist: a spike after a deploy is the negative cache at work.
- SERVFAIL rate plus a probe straight to the authoritative server, because a resolver serving stale answers can stay green while the authoritative is down.