Your NS records live in two places

When a resolver looks up www.example.com, it doesn’t start at your DNS provider. It asks the .com servers, and they reply with a referral: “example.com is served by these nameservers”. That list lives in the parent zone, at the registry. You change it through your registrar’s “nameservers” setting, and its TTL is set by the registry, not by you; for .com it’s 172800 seconds, two days.

Your zone at your DNS provider has its own NS records at the apex. Those are what the nameservers themselves report when asked, and with managed DNS the provider usually fills them in for you.

The two lists are supposed to match, and every server on them is supposed to answer for the zone. “Nameserver mismatch” is the name people use for any of the ways that goes wrong:

  1. You edit records at a provider that isn’t in the registry’s list at all. The most common case by far.
  2. The registry’s list and the zone’s own NS list differ.
  3. A listed server doesn’t serve the zone (lame delegation).
  4. Glue at the registry has an old IP address for a nameserver.
  5. A DNSSEC DS record at the registry doesn’t match the keys of the provider now serving the zone.

The symptoms overlap: changes that never show up, a domain that works on some networks and not others, slow first lookups, or SERVFAIL. The checks below tell them apart.

Step 1: what the registry says

Find a server for your TLD, then ask it about your domain with recursion off:

$ dig +short NS com
a.gtld-servers.net.
b.gtld-servers.net.
...

$ dig @a.gtld-servers.net example.com NS +norecurse

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30411
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1

;; AUTHORITY SECTION:
example.com.     172800  IN  NS  ns1.new-dns.example.
example.com.     172800  IN  NS  ns2.new-dns.example.

There’s no aa flag and the answer section is empty. That’s correct: the parent isn’t authoritative for your NS records, it hands out a referral. For other TLDs, start with dig +short NS net, dig +short NS kr and so on.

The RDAP lookup shows the same nameserver list as the registry has it, along with the domain’s status. If your registrar’s dashboard shows something different from RDAP and the TLD servers, the change hasn’t reached the registry yet, or it failed.

Step 2: what each nameserver says

Now ask every server on that list, and every server in your zone’s own NS records, the same question:

$ dig @ns1.new-dns.example example.com NS +norecurse

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5893
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; ANSWER SECTION:
example.com.     86400   IN  NS  ns1.new-dns.example.
example.com.     86400   IN  NS  ns2.new-dns.example.

This one is healthy: status: NOERROR, the aa flag (authoritative answer), and the same two names the registry lists.

To check them all at once, including the SOA serial each one serves:

parent=$(dig @a.gtld-servers.net example.com NS +norecurse +noall +authority | awk '$4=="NS" {print $5}')
for ns in $parent; do
  echo "== $ns"
  dig @"$ns" example.com SOA +norecurse | grep -E 'status:|flags:|^example\.com\..*SOA'
done

dig +nssearch example.com is a quicker version: it prints the SOA serial from each nameserver the resolver knows about. It uses the zone’s NS list as seen through your resolver, not the registry’s, so it’s a complement to the loop above, not a replacement.

How to read what comes back:

What a server returnsMeaning
NOERROR, aa flag, same serial as the othersHealthy
REFUSEDThe server doesn’t host your zone. Lame.
SERVFAILIt has the zone configured but can’t serve it, often a zone that failed to load on a self-hosted server. Lame.
NOERROR without aaIt’s answering from a cache or as a resolver, not as the authority. Lame.
TimeoutDown, unreachable, or firewalled. Lame from a resolver’s point of view.
aa, but a different serial or different recordsOut of sync: a secondary isn’t getting zone transfers, or this is an old copy of the zone at a previous provider.

Managed providers with anycast networks can briefly show different serials during an update. A difference that lasts is a problem.

The common situations and their fixes

You edited records at a provider that isn’t delegated

You moved to a new DNS provider, or never left the registrar’s DNS, and edited records in a dashboard the world isn’t using. Step 1 shows nameservers from provider A; you made your change at provider B. Every change “doesn’t propagate”, because resolvers never ask B.

Fix: decide which provider should serve the zone. Either make the changes there, or switch the registry’s nameservers to the provider you’ve been editing, after checking it has the complete zone (Step 2 against its nameservers will show you).

The registry list and the zone’s NS list differ

Typical after a migration: the zone file you imported still contains the old provider’s NS records at the apex, or you added a third nameserver at the registrar and forgot the zone, or the other way round.

What resolvers do with a mismatch varies. Some keep using the parent’s list for the whole delegation TTL; others replace it with the NS records from your zone once they’ve seen an authoritative answer, because authoritative data ranks higher. So two resolvers can end up sending queries to different sets of servers. If one set includes an old provider with stale records, you get answers that differ by network for no visible reason.

Fix: make the apex NS records in the zone exactly match the registry’s list. With most managed providers you can’t edit the apex NS records and they’re correct by definition; the mismatch is then on the registry side.

Lame delegation

A listed nameserver doesn’t serve the zone: the old provider deleted it, the account was closed, the nameserver name has a typo, or the nameserver’s own hostname no longer resolves. Resolvers try another server after a failure, so as long as one healthy server remains the domain mostly works, just slowly and unreliably on first lookups. When every listed server is lame, the domain fails with SERVFAIL.

A Cloudflare-specific variant: Cloudflare assigns each zone a particular pair of nameserver names (two *.ns.cloudflare.com names). They aren’t interchangeable. Copying the pair from another domain or another account points the registry at Cloudflare servers that won’t answer for your zone, and the zone stays pending in the dashboard.

Fix: remove the lame servers at the registrar, or fix them so they serve the zone. Don’t leave a server on the list “just in case”; a dead entry costs every resolver that picks it a timeout.

Stale glue

If your nameservers are inside your own domain (ns1.example.com serving example.com), resolvers can’t look up their addresses without already being able to resolve example.com. The registry solves this with glue: the IP addresses of those nameservers, stored at the registry and sent in the referral’s additional section.

$ dig @a.gtld-servers.net example.com NS +norecurse

;; AUTHORITY SECTION:
example.com.        172800  IN  NS  ns1.example.com.
example.com.        172800  IN  NS  ns2.example.com.

;; ADDITIONAL SECTION:
ns1.example.com.    172800  IN  A   198.51.100.53
ns2.example.com.    172800  IN  A   203.0.113.53

Change a nameserver’s IP and update only the A record in your zone, and the registry keeps handing out the old address. Compare the glue with dig @198.51.100.53 ns1.example.com A +norecurse.

Fix: update the glue at the registrar. It’s usually a separate page, called something like “register nameservers”, “host records” or “child nameservers”, not the nameserver list itself.

A DS record left behind after a provider move

If the domain was DNSSEC-signed at the old provider, the registry holds a DS record that fingerprints the old provider’s key. Move to a provider that signs with a different key, or doesn’t sign at all, and validating resolvers find a DS that matches nothing. They treat the zone as bogus and return SERVFAIL. Resolvers that don’t validate keep working, which is why it looks like “works on my ISP, fails on 1.1.1.1 and 8.8.8.8”.

$ dig @a.gtld-servers.net example.com DS +norecurse +noall +answer
example.com.   86400   IN   DS   2371 13 2 9F3A...

$ dig @ns1.new-dns.example example.com DNSKEY +norecurse +noall +answer
(no output: the new provider isn't signing)

$ dig @1.1.1.1 example.com A        # status: SERVFAIL
$ dig @1.1.1.1 example.com A +cd    # status: NOERROR, answer present

+cd asks the resolver to skip validation. If the answer appears with +cd and disappears without it, the problem is DNSSEC, not the records. Recent versions of dig also print an extended error line from resolvers that send one, such as EDE: 9 (DNSKEY Missing). DNSViz (dnsviz.net) draws the whole chain if you want a picture of where it breaks.

Fix, if it’s already broken: either remove the DS at the registrar, or turn on DNSSEC at the new provider and replace the DS with the one it gives you. Validating resolvers recover as the old DS expires from their caches.

The registry hasn’t applied the change yet

You changed the nameservers at the registrar, but Step 1 still shows the old ones. Registrars submit the change to the registry, and how fast that happens varies. Some registries also test the new nameservers before accepting a change, and reject or hold it if they don’t answer for the zone (DENIC does this for .de). If the registry hasn’t picked it up after a few hours, ask the registrar what happened to the request.

Moving DNS providers without creating a mismatch

Most mismatches are created during a move. The order that avoids them:

  1. Copy the whole zone to the new provider. Every record, not just A and MX: TXT for SPF, DKIM and verification, CAA, SRV, every subdomain.
  2. Check it before switching, by querying the new nameservers directly with dig @new-ns ... +norecurse for a list of names.
  3. If the domain uses DNSSEC, remove the DS at the registrar first and wait at least the DS TTL before changing nameservers. Or, if both providers support it, follow a multi-signer key rollover instead.
  4. Change the nameservers at the registrar. Confirm with Step 1 that the registry has them.
  5. Keep the old provider serving an identical zone for at least 48 hours, longer if you can. Resolvers that cached the old delegation keep using it for the delegation TTL. Don’t edit records during this window, or edit at both.
  6. Sign at the new provider and add its DS once the move has settled.
  7. Then remove the zone at the old provider.

The DNS propagation guide explains why the old provider has to stay up, and the TTL guide covers the parent-side TTLs you can’t change. For a move that also changes domain names, see the domain migration checklist.

Checking from outside

The commands above give the most precise answer. For a quick view without a terminal:

  • RDAP lookup: the nameservers and status the registry has.
  • DNS lookup: the NS, SOA and other records as public resolvers return them, with TTLs.
  • Propagation check: whether six public resolvers agree, useful while the old delegation is still cached.

If RDAP and the DNS lookup show different nameservers, you’ve confirmed a mismatch between the registry and the zone, and the sections above tell you which side to fix.

Check your own domain now

Free, no sign-up. Runs the exact check this guide describes and shows what to fix.