Bali, Indonesia
Insights

Lowered DNS TTL Before Migration, but Visitors Still Hit the Old Server

October 27, 2026
0:00
You lowered the TTL on your A record to five minutes, switched the IP to the new server, and the old server's access log is still filling up hours later. Your DNS panel shows the new IP and the short TTL. dig from your laptop returns the new address too. So why do some visitors still land on the old machine? In most cases the TTL was lowered too late. A recursive resolver caches a record for the TTL it received when it last fetched that record. If it fetched the record under the old, longer TTL, it keeps serving the old IP until that timer runs out, whatever you publish afterward. The steps below confirm that this is what's happening, rule out the causes that look similar, and show how to tell when the cutover has actually finished.
Before you blame DNS, look at who is still connecting. The old server's access log tells you whether you're seeing scattered real visitors or a few specific clients that never use DNS the way browsers do.
BASH
# Count requests per client IP on the old server (Nginx path shown; Apache
# and control panels such as cPanel keep per-domain logs elsewhere)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# Watch new requests arrive in real time
tail -f /var/log/nginx/access.log
If you see many different client IPs, each sending a handful of normal page requests, stale resolver caches are the likely cause. If one or two IPs make up most of the traffic, look elsewhere first. Typical culprits are an uptime monitor, a cron job or API client pointed at the IP directly, a developer's hosts file entry, or an application holding a persistent connection that it opened before the switch. Also check whether the domain sits behind a CDN or reverse proxy. In that setup visitors never resolve your origin IP at all. The proxy's origin setting decides where traffic goes, and changing the A record in your zone may do nothing until you update that setting.
The next red herring is editing the wrong zone. It happens often: the record gets changed in the registrar's DNS editor while the domain's nameservers point to the hosting provider, or the other way round. The panel you edited looks correct, but nobody on the internet queries it. Find out which nameservers are authoritative, then ask one of them directly. The +norecurse flag asks the server to answer from its own zone data instead of looking the name up elsewhere.
BASH
# Which nameservers are authoritative for the domain
dig NS example.com +short

# Ask one of them directly for the A record
dig @ns1.example-dns.net example.com A +norecurse +noall +answer

# Then ask several public recursive resolvers what they hold right now
for r in 1.1.1.1 8.8.8.8 9.9.9.9; do
  echo "== $r"
  dig @"$r" example.com A +noall +answer
done
Replace the domain and nameserver with your own. The authoritative answer should show the new IP and the TTL you set, and that TTL stays the same on every query. If it shows the old IP, the change never reached the zone that matters, and waiting won't fix it.
Recursive resolvers count down. The TTL in their answer is the time left before they discard the cached record and ask the authoritative servers again. That one number tells you a lot.
TEXT
Illustrative output format (TTL values are illustrative examples)

== 1.1.1.1
example.com.    243     IN    A    203.0.113.20
== 8.8.8.8
example.com.    61842   IN    A    198.51.100.10
== 9.9.9.9
example.com.    300     IN    A    203.0.113.20
In this sample, the first and third resolvers already hold the new address with a short TTL. The second still has the old IP, and its remaining TTL of 61842 seconds is far above the 300 you now publish. That only makes sense if it cached the record before you lowered the TTL. It will keep handing out the old IP for roughly another 17 hours, and nothing on your side shortens that. Run the loop a few times. Large public resolvers are anycast, meaning many separate server locations share one IP address. Each location can have its own cache, so you may get different answers seconds apart. The ISP resolvers your visitors actually use are harder to sample from outside, which is why the old server's log is still your best signal of how much stale traffic is left.
Here's the timeline that usually produces this symptom, with illustrative numbers. The record had a TTL of 86400 seconds (one day).
  1. A visitor's resolver fetches the record at hour 0 and caches the old IP for 24 hours.
  2. At hour 1 you lower the TTL to 300 seconds.
  3. At hour 2 you change the IP to the new server.
  4. That resolver doesn't ask again until hour 24, so it serves the old IP until then.
The lower TTL is part of the record itself. A resolver only learns about it when it fetches the record again, and a resolver holding a day-long cache entry won't fetch again for up to a day. Lowering the TTL an hour before cutover only helps resolvers whose cache happened to expire in that hour. The fix is about timing. Lower the TTL first, wait at least the full old TTL plus some margin, and only then change the IP. After that wait, every resolver that respects TTLs has re-fetched the record under the short value, so the real switch spreads within minutes. You can confirm the wait is over by sampling resolvers before cutover: every answer should show a remaining TTL at or below your new value. A few other caching layers explain the stragglers that remain even when the timing was right:
  • Some resolvers enforce their own minimum or maximum cache time and ignore very short TTLs.
  • Browsers and operating systems keep their own small DNS caches, so a tab that stayed open may keep using the old IP until it reconnects.
  • Keep-alive and HTTP/2 connections opened before the switch keep talking to the old server until they close.
If you changed nameservers rather than just the A record, there's one more layer. The NS delegation lives at the TLD registry with its own TTL, which you can't lower from your own zone. A nameserver move usually takes longer to settle than a record change for that reason.
On the support desk, the first question worth asking is when the TTL was lowered compared to when the IP changed. The answer usually explains the whole ticket. To decide the cutover is actually done, check three things:
  1. The authoritative nameservers return the new IP.
  2. Repeated samples from several public resolvers return the new IP with a TTL at or below the new value.
  3. Real visitor traffic in the old server's log has dropped to stray clients you can identify, such as monitors or hardcoded integrations.
Until all three hold, keep the old server running. The bigger risk during this window is usually data, not a few slow visitors. If both servers accept writes, orders or comments can land on the old database and disappear after you shut it down. Depending on the setup, you can put the old site into maintenance or read-only mode, or have the old web server proxy requests to the new one so stale-DNS visitors still reach the live application. If the database moves too, make sure it's in sync before switching traffic. See checking that database replication is in sync before cutover for the steps. For the next migration: lower the TTL at least one full old-TTL period ahead, confirm with dig that resolvers are counting down from the new value, then switch. Once traffic has settled on the new server, raise the TTL back to a normal value so resolvers aren't querying your nameservers every few minutes for no reason.