DNS Troubleshooting: dig, Propagation and Common Failures
At a glance#
- Purpose: Diagnose DNS resolution problems methodically and identify where in the chain a lookup is failing.
- Applies to: Any environment; examples use
digon Linux andnslookupon Windows. - Risk: None — all commands are read-only queries.
- Time: 15–45 minutes depending on the fault.
Overview#
"The website is down" is a DNS problem more often than anything else. The difficulty is that DNS failures look identical from the outside regardless of cause — a missing record, a stale cache, a lame delegation and an expired domain all produce the same "site not loading" report.
This article gives a fixed diagnostic order. Work through it top to bottom and the failure isolates itself:
Registrar → Parent zone (delegation) → Authoritative NS → Recursive resolver → Client cacheAlways test from the authoritative end downwards. Testing only from your laptop tells you what your resolver cached, not what is actually published.
Before you start#
- The affected domain name.
- Knowledge of which server should be authoritative for it.
diginstalled (bind-utilson RHEL,dnsutilson Debian/Ubuntu).
Tip: Usedig +shortfor a quick answer and fulldigwhen you need to see the reasoning. Add+tracewhen you do not yet know where the fault is.
The diagnostic sequence#
1. Confirm the domain is actually registered and not expired#
An expired domain removes the delegation entirely, and no amount of server-side work will fix it.
whois example.com | grep -iE "expiry|expiration|status"Look for Expiry Date in the past, or a status of clientHold, serverHold, pendingDelete or redemptionPeriod. Any of those means the registrar has suspended the domain — see Domain Registration, Renewal, DNS Delegation and Transfer.
2. Check the delegation at the parent zone#
This is what the internet believes your nameservers are, and it is frequently wrong after a migration.
dig NS example.com @a.gtld-servers.net +norecurseCompare that with what your own nameservers claim:
dig NS example.com @ns1.example.comWarning: If these two lists disagree, you have a lame delegation. Some resolvers will follow the parent and some will use cached data, so the domain works intermittently and from some networks but not others. This is the single most confusing DNS fault and the one most often misdiagnosed as "propagation".
Fix it at the registrar, not on the server.
3. Query the authoritative server directly#
Bypass every cache and ask the server that actually holds the zone:
dig A example.com @ns1.example.comRead the status: field in the header:
| Status | Meaning | Where to look |
|---|---|---|
NOERROR with an ANSWER section | Record exists and is being served | Problem is downstream — caching or client |
NOERROR with ANSWER: 0 | Domain exists but this record type does not | The record is missing; add it |
NXDOMAIN | The name does not exist in the zone at all | Wrong zone loaded, or typo in the record |
SERVFAIL | Server holds the zone but cannot answer | Zone failed to load, or DNSSEC validation failure |
REFUSED | Server will not answer for this zone | Not authoritative, or ACL blocking the query |
If the authoritative server does not have the record, stop here — nothing downstream matters.
4. Trace the full resolution path#
When the fault is not obvious, follow the delegation from the root:
dig +trace example.comThis queries the root servers, then the TLD servers, then your nameservers, printing each hop. The step where it stops or diverges is the broken link.
5. Compare public resolvers#
If the authoritative answer is correct but users still fail, the problem is caching:
dig +short A example.com @8.8.8.8 # Google
dig +short A example.com @1.1.1.1 # Cloudflare
dig +short A example.com @9.9.9.9 # Quad9Different answers between resolvers means the change is still propagating. Identical wrong answers everywhere means the authoritative record is wrong.
Check how long the stale answer will persist:
dig A example.com @8.8.8.8 | grep -A1 "ANSWER SECTION"The number before the record class is the remaining TTL in seconds. Nothing will change until it reaches zero.
6. Check the client#
Rule out the local machine last:
# Linux
resolvectl status
cat /etc/resolv.conf
resolvectl flush-caches
# Windows
ipconfig /all
ipconfig /displaydns
ipconfig /flushdnsAlso check /etc/hosts — a stale entry there overrides DNS entirely and survives every cache flush.
Common record checks#
# Mail routing
dig MX example.com +short
# SPF and other TXT records
dig TXT example.com +short
# DKIM - selector is provided by the mail platform
dig TXT selector._domainkey.example.com +short
# DMARC
dig TXT _dmarc.example.com +short
# Reverse DNS, needed for mail deliverability
dig -x 192.0.2.10 +short
# Nameservers as published by the zone itself
dig NS example.com +short
# SOA - useful for checking replication between primary and secondary
dig SOA example.com @ns1.example.com +short
dig SOA example.com @ns2.example.com +shortNote: If the SOA serial differs between your primary and secondary nameservers, zone transfer is broken. The secondary is serving stale data and will keep doing so until AXFR succeeds. See BIND9 / NAMED DNS Server – Complete Administration Guide.
Understanding propagation#
"Propagation" is misunderstood constantly. DNS does not push changes anywhere — resolvers pull records and hold them for the TTL. There is no global sync.
Consequences worth explaining to users:
- A change is visible immediately to anyone who had not cached the old value.
- Anyone holding the old record keeps it until their cached TTL expires.
- The maximum wait is the old TTL, the one in effect before you made the change.
- Lowering the TTL after making a change does nothing. It must be lowered beforehand.
Before any planned DNS change, lower the TTL to 300 seconds at least 24 hours ahead. Make the change, confirm it, then raise the TTL back to its normal value.
Verification#
Once the fault is fixed:
# Authoritative servers agree
dig +short A example.com @ns1.example.com
dig +short A example.com @ns2.example.com
# Public resolvers agree
dig +short A example.com @8.8.8.8
dig +short A example.com @1.1.1.1
# Full path is clean
dig +trace example.com | tail -20Then confirm the service itself, not just the record:
curl -sI https://example.com | head -1Troubleshooting#
| Symptom | Likely cause | Fix |
|---|---|---|
SERVFAIL from your own nameserver | Zone file has a syntax error and failed to load | named-checkzone example.com /var/named/example.com.zone |
SERVFAIL only from validating resolvers | DNSSEC records do not match the delegation | Check DS records at the registrar, or disable DNSSEC until fixed |
REFUSED | Server not authoritative, or allow-query ACL blocking | Review named.conf for that zone |
| Works internally, fails externally | Split-horizon DNS, or firewall blocking port 53 from outside | Test from an external host; check UDP and TCP 53 |
| Works for some users only | Lame delegation, or mid-propagation | Compare parent NS records with the zone's own |
| Record correct but site still down | Not a DNS fault | Move on to the web server or firewall |
| Intermittent resolution | One of several nameservers is broken | Query each NS individually |
| Mail bouncing, web fine | MX, SPF or PTR problem | Check MX, TXT and reverse DNS separately |