How-To Guide

DNS Debugging for Developers: Records, Propagation, and Free Lookup Tools

DNS issues are notoriously hard to diagnose. This guide covers A, AAAA, MX, TXT, NS, and CNAME records, how propagation actually works, TTL strategy, common failure patterns, and the browser-based tools you can use without installing dig or nslookup.

DNS failures have a specific torture quality: the system works perfectly for most people and fails intermittently for others, depending on which resolver their ISP or network assigned them. You can spend an hour debugging what turns out to be a resolver cache issue 500 kilometers away.

This guide gives you a systematic debugging process so you're not guessing.

How DNS Resolution Actually Works

When a browser navigates to api.example.com, the following chain runs:

  1. Browser cache — checks if it has a recent answer for this hostname
  2. OS resolver cache — checks /etc/hosts and the OS DNS cache
  3. Recursive resolver — your ISP's resolver, or 8.8.8.8, or 1.1.1.1 — this resolver does the heavy lifting
  4. Root nameservers — there are 13 root nameserver clusters (a.root-servers.net through m.root-servers.net). They know which nameservers are authoritative for .com, .io, .dev, etc.
  5. TLD nameservers — know which nameservers are authoritative for example.com
  6. Authoritative nameservers — your DNS provider (Cloudflare, Route 53, etc.) — these have the actual records

The recursive resolver caches every response at each step according to the TTL on each record. This is why propagation is not instant — it's bounded by the TTLs in place at the time you make a change.

DNS Record Types

A Record

Maps a hostname to an IPv4 address.

api.example.com.  300  IN  A  203.0.113.45

AAAA Record

Maps a hostname to an IPv6 address.

api.example.com.  300  IN  AAAA  2001:db8::1

CNAME Record

Creates an alias from one hostname to another. The target must eventually resolve to an A or AAAA record.

www.example.com.  300  IN  CNAME  example.com.
api.example.com.  300  IN  CNAME  lb-123.us-east-1.elb.amazonaws.com.

Critical constraint: You cannot have a CNAME on an apex domain (example.com). CNAMEs require the target to be another hostname, and DNS doesn't allow other records (like MX or NS) to coexist with a CNAME. Use ALIAS or ANAME records (provider-specific) for apex domains, or A records pointing to IPs.

MX Record

Specifies which mail servers accept email for a domain.

example.com.  300  IN  MX  10  mail1.example.com.
example.com.  300  IN  MX  20  mail2.example.com.

The number is priority — lower is preferred.

TXT Record

Arbitrary text data. Used for:

NS Record

Specifies which nameservers are authoritative for a domain.

example.com.  86400  IN  NS  ns1.cloudflare.com.
example.com.  86400  IN  NS  ns2.cloudflare.com.

SOA Record

Start of Authority — contains administrative information about the zone including the primary nameserver, responsible email, and serial number. Changes to the serial number signal secondary nameservers to refresh.

Understanding TTL and Propagation

TTL (Time to Live) is the number of seconds a resolver should cache a record before re-querying. A TTL of 300 means resolvers can cache the answer for 5 minutes.

"DNS propagation" is a misnomer. DNS doesn't push changes to all resolvers — resolvers pull fresh data when their cache expires. So when you change a DNS record:

This has a practical implication: lower your TTL before you make a change.

Standard operating TTL: 3600 (1 hour)
Pre-migration TTL: 300 (5 minutes)  ← set this 24 hours before the change
Migration: change the A record
Post-migration: raise TTL back to 3600 after traffic confirms working

If you change your A record from IP-A to IP-B with a TTL of 86400 (24 hours), some users will continue hitting IP-A for up to 24 hours. Some resolvers (particularly mobile networks) don't honor TTL and cache aggressively for even longer.

Why different users see different results

After a DNS change, you may see your site correctly (because your resolver fetched the new record) while a colleague in another city still sees the old IP (their resolver's cache hasn't expired).

Tools like Google's 8.8.8.8 and Cloudflare's 1.1.1.1 tend to propagate changes faster than ISP resolvers. When testing, always query multiple resolvers.

Debugging DNS Without Installing Any Tools

Browser-based DNS lookup

DeveloperLab's Public DNS Lookup tool queries Cloudflare's DNS-over-HTTPS API (1.1.1.1/dns-query) directly from your browser — no dig, no nslookup, no terminal required.

Enter any hostname and select the record type. Results show the full answer section including all returned values and their TTLs.

DNS-over-HTTPS API (manual)

You can query 1.1.1.1 directly from any fetch-capable environment:

const hostname = 'api.example.com';
const type = 'A'; // A, AAAA, MX, TXT, NS, CNAME

const res = await fetch(
  `https://cloudflare-dns.com/dns-query?name=${hostname}&type=${type}`,
  { headers: { Accept: 'application/dns-json' } }
);
const data = await res.json();
console.log(data.Answer); // array of records with TTL and data

For Google's resolver:

https://dns.google/resolve?name=api.example.com&type=A

Querying both Cloudflare and Google in parallel gives you a quick cross-resolver consistency check.

Command-line tools

When you do have terminal access:

# Query specific resolver (Cloudflare)
dig @1.1.1.1 api.example.com A

# Check propagation across multiple resolvers
dig @8.8.8.8 api.example.com A
dig @9.9.9.9 api.example.com A  # Quad9
dig @208.67.222.222 api.example.com A  # OpenDNS

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

# Check TTL remaining in your local cache (macOS)
sudo killall -INFO mDNSResponder  # flush cache on macOS

Common DNS Failure Patterns

NXDOMAIN (Non-Existent Domain)

The record doesn't exist at the authoritative nameserver.

$ dig api.example.com A
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN

Common causes:

SERVFAIL

The authoritative nameserver is unavailable or misconfigured.

;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL

Common causes:

Stale cache after migration

You changed the record but some users still hit the old server.

Diagnosis:

# Check TTL remaining (how long until this resolver refreshes)
dig api.example.com A +noall +answer
# example.com.  47  IN  A  203.0.113.45
#               ^^-- 47 seconds until this cache entry expires

Fix: Lower TTL before the next migration. For users already cached on the old IP, wait for their TTL to expire — you cannot force their resolver to flush.

CNAME flattening issues

You configured a CNAME on your apex domain and MX records stopped working.

Problem: DNS spec forbids CNAME coexistence with other record types. Some providers silently break MX, TXT, or NS records when a CNAME is present at the apex.

Fix: Use your provider's ALIAS/ANAME record type instead of CNAME for apex domains. Route 53, Cloudflare, DNSimple all support this. The alias is resolved server-side before being returned as an A record to the resolver.

Subdomain takeover

A CNAME points to an external service (S3 bucket, Heroku app, GitHub Pages) that no longer exists. An attacker can claim that resource and serve content from your subdomain.

# Check for dangling CNAMEs
dig legacy.example.com CNAME
# legacy.example.com CNAME old-app.herokuapp.com.
dig old-app.herokuapp.com A
# NXDOMAIN — nobody owns this anymore

Audit all CNAME records pointing to cloud providers and delete any that resolve to NXDOMAIN.

Email DNS (SPF, DKIM, DMARC)

Email deliverability depends entirely on three TXT records being correctly configured:

SPF (Sender Policy Framework)

Specifies which IP addresses and services are authorized to send mail for your domain.

v=spf1 include:_spf.google.com include:sendgrid.net ~all

DKIM (DomainKeys Identified Mail)

A cryptographic signature attached to outgoing emails, verified against a public key in your DNS.

selector1._domainkey.example.com  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkqhk..."

The selector prefix is set by your email provider. You may have multiple selectors (one per provider).

DMARC (Domain-based Message Authentication)

Tells receiving servers what to do when SPF or DKIM fail, and where to send reports.

_dmarc.example.com  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; pct=100"

To debug email deliverability, check all three records:

dig example.com TXT              # SPF
dig selector1._domainkey.example.com TXT  # DKIM
dig _dmarc.example.com TXT       # DMARC

Or use DeveloperLab's DNS Lookup tool — paste the hostname and select TXT to inspect all three without a terminal.

DNS Debugging Workflow

When something breaks that might be DNS:

1. Can you reach the IP directly?
   curl -H "Host: api.example.com" http://203.0.113.45/health
   → If yes: DNS problem. If no: server problem.

2. What does your local resolver think?
   dig api.example.com A

3. What does the authoritative nameserver think?
   dig @$(dig example.com NS +short | head -1) api.example.com A

4. Are Cloudflare and Google resolvers consistent?
   dig @1.1.1.1 api.example.com A
   dig @8.8.8.8 api.example.com A

5. What TTL is cached at your resolver?
   Check the TTL field in the dig output — that's how long until refresh.

6. Is the answer correct but the IP wrong?
   → Change the record and wait for TTL to expire.

7. Is there no answer at all (NXDOMAIN)?
   → Check the record exists in your DNS provider dashboard.
   → Check you're querying the right zone.

DNS problems are almost always in one of three places: the record doesn't exist, the record points to the wrong value, or caches haven't expired yet. Systematic queries to multiple resolvers let you distinguish between them quickly.