DNS Explained - Resolution, Records, and TTLs End to End
Status: Active
Last Updated: 2026-08-26
Category: Networking - DNS Fundamentals
Prerequisites: dns-fundamentals, tcp-ip-fundamentals
Time: 2 hours
Tags: dns, resolution, records, ttl, caching, recursive
Summary
Walks a single DNS query from your laptop to an authoritative nameserver and back: resolvers, root/TLD/authoritative hierarchy, the record types a homelab actually uses, and how TTLs govern caching and "propagation." The companion article dns-management covers operating our own zones.
๐ฏ What You'll Learn
By the end of this article, you'll be able to:
- โ
Trace a full recursive resolution with
dig +trace - โ Choose the right record type (A/AAAA/CNAME/SRV/TXT/NS/MX) for each job
- โ Predict how long clients cache a change based on TTL
- โ Diagnose NXDOMAIN vs SERVFAIL vs timeouts correctly
Table of Contents
- Context / Why This Matters
- The Resolution Walkthrough
- Record Types That Matter
- TTLs and "Propagation"
- Failure Modes
- Troubleshooting & Common Pitfalls
- Next Steps / Ops Actions
- Sources & Related
- Change Log
Context / Why This Matters
Every service in the fogserv fleet is reached by name โ public via Cloudflare, internal via local overrides (dhcp-dns-split-horizon). When a name doesn't resolve, nothing else matters. Understanding where resolution can fail turns "the internet is down" into a 30-second diagnosis.
The Resolution Walkthrough
Resolving grafana.fogserv.cloud:
stub resolver (your OS)
โ asks configured recursive resolver (e.g., 1.1.1.1 or your router)
1. Root servers: "who handles .cloud?" โ TLD nameservers
2. .cloud TLD: "who is NS for fogserv.cloud?" โ Cloudflare NS
3. Authoritative NS: returns A record + TTL
โ answer cached by resolver for TTL seconds, returned to stub
Key points:
- Stub vs recursive vs authoritative: your OS stub never talks to roots; the recursive resolver does the legwork and caches; authoritative servers own the actual data.
- Caching happens at every layer, each honoring the record's TTL.
- Watch it live:
dig +trace grafana.fogserv.cloud A # full walk, no cache
dig @1.1.1.1 grafana.fogserv.cloud # ask a specific resolver
;; ANSWER SECTION:
grafana.fogserv.cloud. 300 IN A 203.0.113.10
^^^ TTL in seconds this resolver may cache it
Record Types That Matter
| Type | Purpose | Example |
|---|---|---|
| A / AAAA | name โ IPv4 / IPv6 | edge.fogserv.cloud. IN A 203.0.113.10 |
| CNAME | alias to another name (never at zone apex) | grafana CNAME edge.fogserv.cloud |
| NS | delegates a zone | set by registrar/host |
| MX | mail routing (we don't run mail; keep records empty or intentional) | โ |
| TXT | verification tokens (Cloudflare ACME, SPF) | _acme-challenge for DNS-01 |
| SRV | service discovery (_service._proto) |
rare; some mesh tools use it |
Rules of thumb: apex (fogserv.cloud) must be A/AAAA/ALIAS-style โ that's why Cloudflare offers "CNAME flattening" at the apex. Everything else under the zone can be a plain CNAME to the edge host.
TTLs and "Propagation"
There is no push mechanism โ "propagation" is just caches expounding their TTLs until they expire.
- Low TTL (60โ300s): fast changes, more resolver queries. Use on anything you might repoint (edge host, DDNS targets โ see dynamic-dns).
- High TTL (3600โ86400s): stable infra, fewer queries.
- Before a planned change: lower the TTL ~one old-TTL in advance, make the change, raise TTL back afterward.
# What does the world see right now?
dig @8.8.8.8 edge.fogserv.cloud +short
dig @1.1.1.1 edge.fogserv.cloud +short
# Check remaining cache time at Google's resolver (authority section shows min TTL)
dig @8.8.8.8 edge.fogserv.cloud | grep -A2 "AUTHORITY"
Failure Modes
| Response | Meaning | Where it broke |
|---|---|---|
NXDOMAIN |
name genuinely doesn't exist per authority | typo, deleted record, wrong zone |
SERVFAIL |
authority unreachable/bogus (often DNSSEC) | NS down, broken delegation, clock skew |
| timeout | network path to resolver dead | local resolver down, firewall UDP/53 |
| stale-but-wrong answer | cached old record | wait out TTL or flush local cache |
sudo systemd-resolve --flush-caches # systemd-resolved
sudo dscacheutil -flushcache # macOS
Practical Examples
Diagnose "site is down" in four commands:
dig grafana.fogserv.cloud # resolves? if yes โ not DNS
dig @1.1.1.1 grafana.fogserv.cloud # same answer from upstream?
dig fogserv.cloud NS # correct nameservers delegated?
curl -v https://grafana.fogserv.cloud # TCP/TLS layer then (see tls-configuration)
If direct-authority answers differ from resolver answers, you're looking at a cache problem, not a config problem.
Troubleshooting & Common Pitfalls
| Problem | Cause | Fix |
|---|---|---|
| Change visible on phone but not laptop | Different resolvers, different cache ages | Query both resolvers directly; wait out TTL |
| Apex record won't accept CNAME | RFC rule against CNAME at zone apex | Use A/AAAA or Cloudflare CNAME flattening |
| New record "doesn't work" immediately | Negative cache: previous NXDOMAIN was cached | Wait for SOA negative TTL (often 5โ15 min) |
| Intermittent resolution failures on one host | Wrong/broken local resolver config | Check /etc/resolv.conf, systemd-resolved |
| Certbot DNS-01 fails despite TXT visible locally | TXT not yet propagated to authority | Verify with dig TXT _acme-challenge... @<auth-ns> |
Next Steps / Ops Actions
- Operate our zones deliberately: dns-management
- Host the zone at Cloudflare: cloudflare-dns
- Serve internal names: dhcp-dns-split-horizon
Sources & Related
External references consulted:
- https://www.rfc-editor.org/rfc/rfc1034
- https://www.cloudflare.com/learning/dns/what-is-dns/
- https://jvns.ca/blog/2022/04/12/a-dns-resolver-in-80-lines-of-go/
Related knowledge-base articles:
Change Log
2026-08-26
- Initial creation: end-to-end resolution walkthrough, record types, TTL strategy, failure modes.