Skip to main content

dig and DNS Debugging

DNS bugs are notorious for showing up as "it works for me" - the same name resolving differently on two machines, or a change that took effect for some users and not others. dig is the tool for pulling apart exactly what a resolver answered and why; see DNS in Practice for the record types and TTL/caching concepts this page assumes.

The basic query

$ dig example.com
 
; <<>> DiG 9.10.6 <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51423
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
 
;; QUESTION SECTION:
;example.com. IN A
 
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34
 
;; Query time: 24 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Sun Aug 02 10:20:11 UTC 2026
;; MSG SIZE rcvd: 56

The parts that matter for debugging:

  • status: NOERROR - the query succeeded; NXDOMAIN means the name does not exist, SERVFAIL means the authoritative or recursive server errored.
  • ANSWER SECTION - the actual record(s) returned, with their TTL (86400 seconds here) - how much longer this answer will be cached.
  • AUTHORITY SECTION - present instead of an answer on an NXDOMAIN, or alongside a referral; shows which nameservers are authoritative for the zone. Useful for confirming delegation is set up correctly.
  • SERVER - which resolver actually answered. This is the first thing to check when two machines disagree.

"Works on one machine, not another"

This symptom is almost always one of two things, and dig distinguishes them directly:

  1. Stale cache - one machine (or its resolver) cached an old answer before a record changed, and its TTL has not yet expired. Query the same name against a few different resolvers and compare:

    $ dig @8.8.8.8 example.com +short
    93.184.216.34
    $ dig @1.1.1.1 example.com +short
    93.184.216.34
    $ dig example.com +short # local/corporate resolver
    198.51.100.7

    If the local resolver disagrees with public ones, it is very likely serving a cached answer from before the record was updated, or split-horizon (see below). Waiting out the TTL, or flushing the local resolver's cache, resolves it.

  2. Split-horizon DNS - the two machines are genuinely supposed to get different answers, because they are asking from different networks (e.g. one is on the office VPN, one is not) and the authoritative server is intentionally serving an internal address to one and a public address to the other. dig @<resolver> from each network, pointed at the same authoritative server, confirms whether the difference is deliberate zone config rather than a caching bug.

Gotcha

Comparing dig output from two machines is meaningless if you don't also compare which resolver answered (the SERVER line). Two machines using two different resolvers can legitimately show different TTLs remaining, or different answers under split-horizon, without either being "wrong."

Tracing the full delegation path

dig +trace walks the resolution from the root down, exactly the way a recursive resolver would, instead of trusting a single resolver's cached answer:

$ dig +trace example.com
 
. 518400 IN NS a.root-servers.net.
;; Received 239 bytes from 192.168.1.1#53 in 12 ms
 
com. 172800 IN NS a.gtld-servers.net.
;; Received 827 bytes from a.root-servers.net#53 in 18 ms
 
example.com. 172800 IN NS ns1.example.com.
;; Received 128 bytes from a.gtld-servers.net#53 in 22 ms
 
example.com. 86400 IN A 93.184.216.34
;; Received 56 bytes from ns1.example.com#53 in 9 ms

This is the tool for diagnosing delegation problems - a missing or wrong NS record at the registrar, a zone that lost its glue records, or a nameserver that is unreachable. A plain dig only shows you the recursive resolver's final answer (or cached failure); +trace shows you exactly which step in the chain broke.

Querying a specific resolver directly

dig @<resolver> <name> bypasses whatever resolver your OS is configured to use and asks a specific one - essential for the "works on one machine" case above, and for checking whether a change has propagated to a particular public resolver yet:

$ dig @1.1.1.1 example.com +short
93.184.216.34

Reverse lookups

dig -x <ip> asks for the PTR record - the hostname associated with an IP, the reverse of a normal lookup. Useful for identifying an unfamiliar IP in a log file, or confirming that a mail server's reverse DNS matches its forward DNS (many mail providers reject mail from IPs that fail this check):

$ dig -x 93.184.216.34 +short
example.com.

nslookup: the older alternative

nslookup predates dig and is still installed everywhere (including Windows, where dig often is not), but its output is less detailed and its interactive mode is clunkier to script against:

$ nslookup example.com
Server: 192.168.1.1
Address: 192.168.1.1#53
 
Non-authoritative answer:
Name: example.com
Address: 93.184.216.34
tip

Reach for nslookup only when dig genuinely is not available (stock Windows, some minimal containers). Everywhere else, dig gives you the TTL, the full ANSWER/AUTHORITY/ADDITIONAL sections, and +trace/+short flags that nslookup cannot match.

Facts

dig +short strips everything but the answer data itself - the fastest way to get a value into a shell variable or script without parsing the full output.