On any current version of macOS, one command clears the DNS cache: sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder. It takes a second and it is worth knowing. It is also, most of the time, not what is wrong — the stale record is usually somewhere other than your machine.
Working out which layer is holding the old answer takes about thirty seconds and saves you from flushing caches that were never the problem, which is the usual outcome when a DNS change does not seem to take effect.
Table of contents
- The command
- Finding out where the stale record actually is
- Why dig and ping can disagree
- The caches above your machine
- Browsers cache separately
- When it is not DNS
- How this fits the rest of the stack
- FAQ
The command
Both halves are needed, and they do different things:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
dscacheutil -flushcache clears the Directory Service cache. Sending HUP to mDNSResponder makes the process that actually resolves DNS on macOS reload and drop its cache. Running only the first is why people report that flushing did not work.
On older versions the process was named differently — mDNSResponder on most releases, discoveryd on a couple of unfortunate ones around 10.10. If killall reports no matching process, that is the reason; on any recent system the command above is correct.
There is no output on success. Silence means it worked.
Finding out where the stale record actually is
Before flushing anything, work out which layer is answering. There are four candidates and they are easy to distinguish.
Query an authoritative public resolver directly, bypassing everything local:
dig @1.1.1.1 example.com +short
Then query through your normal path:
dig example.com +short
Interpret the comparison:
- Both show the old value — the change has not propagated, or was never made correctly. Nothing on your machine will help.
- Public resolver shows new, yours shows old — the cache is between you and the internet: your router or your ISP’s resolver.
- Both show new but the browser shows old — your machine or your browser is caching. Now flushing is the right move.
- dig shows new and an application still fails — the application is caching independently, which several runtimes do.
That single comparison settles it, and it is why reaching for the flush command first is usually wasted effort.
Why dig and ping can disagree
A confusing detail specific to macOS: dig does not use the system resolver. It talks to the nameservers in /etc/resolv.conf directly and bypasses mDNSResponder entirely.
So dig can show the new address while ping, curl, and your browser all still use the old one — because those go through the system resolver and its cache.
To test what the system resolver actually returns, use the macOS-specific tool:
dscacheutil -q host -a name example.com
Or simply:
ping -c 1 example.com
If dscacheutil shows the old address and dig shows the new one, the system cache is stale and the flush command is exactly right. This is the one situation where flushing is unambiguously the answer, and knowing how to confirm it is worth more than knowing the command.
The caches above your machine
When the stale record is not local, it is in one of these, and none is cleared by anything you run on the Mac:
- Your router. Many home routers cache DNS. Rebooting it clears that cache and is the only control you have.
- Your ISP’s resolver. Caches according to the record’s TTL and cannot be flushed by you. Switching your machine to a public resolver bypasses it entirely.
- Public resolvers. Also respect TTL. Some offer a web form to purge a specific name from their cache.
- Anything in the delivery path, if the hostname is behind a CDN or proxy with its own resolution cache.
The controlling number in all of these is the record’s TTL, set on the DNS record itself. A record with a 24-hour TTL can be cached for 24 hours by every resolver that saw the old value, and there is no mechanism to force them to forget it early.
This is why the standard advice before a planned migration is to lower the TTL to something short — 300 seconds — a day or two beforehand. Then the cutover propagates in minutes rather than a day, and you can raise the TTL again once it has settled.
Browsers cache separately
One more layer that catches people: browsers maintain their own DNS caches independent of the operating system. A flushed system cache does not clear the browser’s.
Chrome exposes a control at chrome://net-internals/#dns with a button to clear the host cache. Firefox and Safari are less accessible; restarting the browser is the practical answer.
The fastest way to rule the browser out entirely is to test outside it:
curl -sI https://example.com | head -1
If curl reaches the new server and the browser does not, the browser cache is the remaining culprit. Note that a private or incognito window does not necessarily use a separate DNS cache, so that is not a reliable test.
One thing that is not DNS at all but presents identically: HSTS and connection reuse. A browser holding an open connection to the old address keeps using it regardless of what DNS says. Restarting the browser clears that too, which is part of why restarting appears to fix DNS problems that were not DNS problems.
When it is not DNS
A useful last check, because a surprising share of these investigations end here.
If dig, dscacheutil, and curl all return the correct new address and the site still shows old content, DNS resolved correctly and something else is serving stale data — a CDN cache, a reverse proxy, or the application’s own cache.
The distinguishing test: fetch by IP with an explicit host header, bypassing DNS entirely.
curl -sI --resolve example.com:443:203.0.113.10 https://example.com | head -1
If that returns the correct content, DNS was never the problem — you are reaching the right server and something in between is caching the response. If it returns the old content, the server itself is serving it.
That command is worth remembering. It separates resolution from delivery, which is the ambiguity at the heart of nearly every it-has-not-updated-yet report.
How this fits the rest of the stack
The theme here is that a caching problem is only tractable once you know which cache is holding the old value, and most of the time it is not the one in front of you. The same applies to a deployed site: a stale page can be DNS, an edge cache, or the application, and the diagnosis is the same layered elimination. Custom domains and certificates on RunxBuild covers attaching a hostname and what happens at cutover, and response headers are declared rules, which makes cache behaviour something you configure rather than infer. If you are sizing a site alongside its API and database, the RunxBuild hosting calculator itemises them.
Useful related references:
- dnsmasq Cache: Configure, Measure, and Flush Local DNS Safely
- Flush DNS Command: ipconfig, systemd-resolved, and macOS
- Command Prompt Flush DNS: ipconfig, PowerShell, and DNS Client Service
- Custom domains and certificates on RunxBuild
FAQ
What is the command to flush DNS on macOS?
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder. Both parts are needed — the first clears the Directory Service cache and the second makes the actual resolver drop its own. There is no output on success.
Why does dig show the new IP but my browser shows the old one?
On macOS dig bypasses the system resolver and queries nameservers directly, while browsers go through mDNSResponder and its cache. Use dscacheutil -q host -a name example.com to see what the system resolver actually returns.
How do I know if the stale record is on my machine?
Compare dig @1.1.1.1 example.com against dig example.com. If the public resolver shows the new value and yours shows the old one, the cache is between you and the internet. If both show old, it has not propagated.
Can I force my ISP to clear its DNS cache?
No. Resolvers cache according to the record’s TTL and there is no way to purge them from outside. Switch to a public resolver to bypass it, or lower the TTL before a planned change so propagation is fast.
The site still shows old content after DNS updated. Why?
DNS resolved correctly and something else is caching — a CDN, a proxy, or the application. Test with curl —resolve to bypass DNS entirely; if that returns correct content, resolution was never the problem.