DNS issues are deceptively simple. “It’s always DNS” is a meme because it’s true. Here’s how to actually debug it.

The Essential Commands

dig: Your Primary Tool

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Basic lookup
dig example.com

# Short answer only
dig +short example.com

# Specific record type
dig example.com MX
dig example.com TXT
dig example.com CNAME

# Query specific nameserver
dig @8.8.8.8 example.com

# Trace the full resolution path
dig +trace example.com

Understanding dig Output

;;;;e;;;;;e;x;;;;xaQaAmQSWMUmNpuEHSEpSleREGSlWerVNDTeE.yE:SiI.RcRIGOcot:SZNoSmiaE9mE.m1t.S.Ce91ET:2Fr8CI.ec.TO21bv1IN36dO:82:Nm.8:s15e.26c10#:e53x330a6(:m010p090l2e.E.1Sc6ToII8mNN.210.216)AA93.184.216.34

Key fields:

  • 3600 — TTL in seconds (how long to cache)
  • SERVER — Which DNS server answered
  • Query time — Latency (high = problem)

Common Issues and Fixes

1. Record Not Propagated Yet

1
2
3
4
5
6
7
8
9
# Check multiple DNS servers
dig @8.8.8.8 example.com      # Google
dig @1.1.1.1 example.com      # Cloudflare
dig @208.67.222.222 example.com  # OpenDNS

# Check authoritative nameservers directly
dig NS example.com +short
# Returns: ns1.registrar.com
dig @ns1.registrar.com example.com

If authoritative server has the record but public DNS doesn’t, wait for TTL.

2. Wrong Nameservers

1
2
3
4
5
# What nameservers are authoritative?
dig NS example.com

# What does the registrar think?
whois example.com | grep -i "name server"

If these don’t match, update at your registrar.

3. CNAME Conflicts

1
2
3
4
5
6
# This will fail:
dig example.com MX
# Returns: CNAME to something.cdn.com

# CNAMEs can't coexist with other records at the same name
# Use ALIAS/ANAME records instead (if your DNS supports it)

4. Missing Trailing Dot

1
2
3
# In zone files, this matters:
www    CNAME   example.com     # Wrong: becomes example.com.example.com
www    CNAME   example.com.    # Correct: absolute domain

5. Negative Caching

1
2
3
4
5
# Query for non-existent record
dig notreal.example.com

;; AUTHORITY SECTION:
example.com.  300  IN  SOA  ns1.example.com. admin.example.com. ...

The SOA record’s negative TTL (minimum field) controls how long “does not exist” is cached.

Debugging Resolution Path

1
2
3
4
5
6
7
8
# Full trace from root servers
dig +trace example.com

# Shows:
# 1. Root servers (.)
# 2. TLD servers (.com)
# 3. Authoritative servers (example.com)
# 4. Final answer

If trace fails at a specific level, that’s your problem area.

Local DNS Issues

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# What DNS server is the system using?
cat /etc/resolv.conf

# Test if local resolver works
dig @127.0.0.1 example.com

# Bypass local DNS entirely
dig @8.8.8.8 example.com

# Flush local DNS cache (varies by OS)
# macOS
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

# systemd-resolved
sudo systemd-resolve --flush-caches

Record Types Reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# A: IPv4 address
dig example.com A

# AAAA: IPv6 address  
dig example.com AAAA

# CNAME: Alias to another domain
dig www.example.com CNAME

# MX: Mail servers (with priority)
dig example.com MX

# TXT: Text records (SPF, DKIM, verification)
dig example.com TXT

# NS: Nameservers
dig example.com NS

# SOA: Start of authority (zone metadata)
dig example.com SOA

# CAA: Certificate authority authorization
dig example.com CAA

TTL Strategy

1
2
3
4
5
6
# Before making changes, lower TTL
example.com.  300  IN  A  93.184.216.34  # 5 minutes

# Wait for old TTL to expire, then make change
# After verified, raise TTL back
example.com.  86400  IN  A  93.184.216.34  # 24 hours

Low TTL = faster propagation, more DNS queries. High TTL = slower propagation, less DNS load.

Testing Email DNS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# MX records (mail servers)
dig example.com MX

# SPF record (who can send mail)
dig example.com TXT | grep spf

# DKIM record (email signing)
dig selector._domainkey.example.com TXT

# DMARC policy
dig _dmarc.example.com TXT

Scripting DNS Checks

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!/bin/bash
# Check if DNS has propagated

DOMAIN="example.com"
EXPECTED_IP="93.184.216.34"
DNS_SERVERS="8.8.8.8 1.1.1.1 208.67.222.222"

for server in $DNS_SERVERS; do
    result=$(dig @$server +short $DOMAIN | head -1)
    if [ "$result" = "$EXPECTED_IP" ]; then
        echo "✓ $server: $result"
    else
        echo "✗ $server: $result (expected $EXPECTED_IP)"
    fi
done

Quick Diagnosis

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# "DNS isn't working"
dig +short google.com
# No output? DNS server unreachable

# "Website not loading"
dig +short mysite.com
# Returns IP? DNS is fine, problem is elsewhere

# "Email not being received"
dig MX example.com +short
# No MX records? There's your problem

# "SSL certificate error"
dig CAA example.com +short
# CAA restricting wrong CA?

The Nuclear Option

When nothing makes sense:

1
2
3
4
5
6
7
8
# Query root servers directly
dig @a.root-servers.net example.com +trace

# Check if domain is even registered
whois example.com

# Verify zone file syntax (if you control DNS)
named-checkzone example.com /path/to/zone/file

DNS debugging is methodical: start at the source (authoritative servers), work outward (public resolvers), check caching (TTLs). Most issues are either propagation delays or configuration mistakes.