The short answer

DNS that fails only some of the time is nearly always a difference between paths: one of several name servers is broken, one resolver in a pool behaves differently, one address family is unreachable, or large responses are being dropped. Resolvers retry and cache, which hides the fault most of the time. The way to find it is to stop testing "DNS" as a whole and test each server, each resolver and each transport separately until one of them fails every time.

Common causes

CauseWhat you notice
One lame or out-of-date name serverFailures or old answers for a share of lookups, roughly in proportion to how often resolvers pick that server
Name servers with different SOA serialsMay indicate a stalled transfer in a shared primary/secondary topology; independent primaries can have different serials, so compare RRsets
Large responses droppedLookups for DNSSEC-signed names, big TXT records or long MX sets fail, small ones work. Usually a firewall blocking fragments or TCP port 53. See EDNS and TCP fallback.
IPv6 path brokenSlow or failing lookups on dual-stack networks while IPv4-only tests pass
Rate limitingFailures during bursts, for example from monitoring or mail servers, that clear on their own
Short TTLs on a slow zoneLookups work while cached and fail each time the cache expires and the authoritative servers are slow to answer
A resolver pool with one bad memberBehind one resolver address, some backends validate DNSSEC, filter, or have stale caches and others do not

Testing each path

Run the same query several times against each target and note the response code, the flags and the time. Ask each authoritative server directly:

CommandWhat it isolates
dig +norecurse @ns1.example.net example.com SOAOne authoritative server; compare serials for transfer-based secondaries and actual RRsets across independent primaries
dig -6 +norecurse @ns1.example.net example.com SOAThe same server over IPv6
dig +tcp +norecurse @ns1.example.net example.com DNSKEYWhether TCP to the server works
dig +notcp +ignore +bufsize=1232 +dnssec @ns1.example.net example.com DNSKEYA large UDP answer at the size most resolvers now use
dig @1.1.1.1 example.com A and dig @8.8.8.8 example.com APublic resolvers, to compare with your own

A loop can reveal intermittent failure, but 50 independent queries at a 2 percent failure probability have only a 63.6 percent chance of seeing even one failure. About 149 give a 95 percent chance; neither guarantees detection, and correlated failures require sampling across times and paths. The UDP command above uses +notcp +ignore to prevent an automatic TCP retry from hiding truncation; compare it with a separate +tcp query. When a resolver gives SERVFAIL, look for an Extended DNS Error (EDE) in the reply; Cloudflare and Google include one that often names the cause.

Fixing it

  • Remove or repair any name server that fails, and keep the parent's NS list and the zone's NS records the same.
  • For transfer-based secondaries, check convergence to the primary’s SOA serial and investigate stalled transfers. For independent primaries, compare the intended RRsets and provider synchronization rather than requiring identical serials.
  • Allow DNS over TCP port 53 in both directions, and stop dropping UDP fragments, or keep responses under about 1,232 bytes.
  • Fix or remove AAAA records for name servers that cannot be reached over IPv6.
  • Raise very short TTLs on stable records so each cache miss matters less.

How DNS Panopticon helps

Domain Visualizer runs one set of lookups through a public DNS-over-HTTPS resolver, so it sees the domain from one path at one moment. Choosing a second resolver adds a comparison and a resolver variance finding when the answers differ. It also reports a name server host with no address and a zone with only one name server. It does not query each authoritative server, repeat lookups, or test UDP and TCP separately, so intermittent faults need the per-path tests above.

Sources and further reading