The largest distributed database in the world, your first load balancer, your slowest failover mechanism, and a shockingly common cause of total outages.
Prerequisites: Networking 101 Time to read: ~16 minutes
Servers are found by IP address: 93.184.216.34. Humans cannot remember those, and more
importantly, IPs change — you replace a server, add a region, fail over to a backup. If every
client hard-coded an IP, every change would break every client.
So you need a layer of indirection: a name that maps to an address, where the mapping can change without anyone updating their code.
That’s DNS. And because it’s indirection, it also becomes the place where you do global load balancing, geographic routing, and failover.
You want “Café Aroma” and only know the name.
.com desk.”).com desk says “Café Aroma’s own office handles their locations, here’s their number.”
(TLD server → authoritative nameservers.)The hierarchy is what makes DNS scale: no single machine knows everything, and each level only knows who to delegate to.
sequenceDiagram
participant App
participant OS as OS cache
participant R as Recursive resolver<br/>(8.8.8.8)
participant Root as Root (.)
participant TLD as .com TLD
participant Auth as ns1.example.com
App->>OS: api.example.com?
Note over OS: miss
OS->>R: api.example.com?
R->>Root: api.example.com?
Root-->>R: ask the .com servers
R->>TLD: api.example.com?
TLD-->>R: ask ns1.example.com
R->>Auth: api.example.com?
Auth-->>R: 93.184.216.34, TTL 300
R-->>OS: 93.184.216.34
Note over R: cached for 300 s
📐 Cost: a fully cold lookup is 20–120 ms (four sequential round trips). A cached one is ~0 ms. In practice the vast majority of lookups are cached somewhere in that chain, which is the only reason the root servers survive.
The caching layers, in order: browser cache → OS resolver cache → recursive resolver cache → (finally) authoritative. Each holds the answer for the record’s TTL.
| Type | Maps | Example | Notes |
|---|---|---|---|
| A | name → IPv4 | example.com → 93.184.216.34 |
The basic one |
| AAAA | name → IPv6 | example.com → 2606:2800:220:1:: |
“quad-A” |
| CNAME | name → another name | www.example.com → example.com |
Cannot coexist with other records at the same name; cannot be used at the zone apex (example.com itself) |
| ALIAS / ANAME | apex → another name | example.com → lb.aws.com |
Provider-specific fix for the CNAME-at-apex limitation |
| MX | mail servers | example.com → mail.example.com (pri 10) |
Priority-ordered |
| TXT | arbitrary text | SPF, DKIM, domain verification | How every SaaS proves you own the domain |
| NS | delegation | example.com → ns1.provider.com |
Who is authoritative |
| SRV | service + port | _sip._tcp.example.com → 5060 sip.example.com |
Used by service discovery, SIP, Kubernetes |
| PTR | IP → name | reverse lookup | Mail servers check this for spam scoring |
| CAA | which CAs may issue certs | Prevents rogue certificate issuance |
🚨 The CNAME-at-apex limitation trips up almost everyone once. You cannot CNAME example.com to a
load balancer hostname, because the apex must also hold NS and SOA records. Use your provider’s
ALIAS/ANAME record, or an A record pointing at a static IP.
The TTL says how long resolvers may cache an answer.
| TTL | Good | Bad |
|---|---|---|
| 60 s | Failover in ~1 minute; agile | ~50× more query volume; more cold lookups (slower for users) |
| 3600 s (1 h) | Balanced default | Failover takes up to an hour |
| 86400 s (24 h) | Cheapest, fastest for users | A mistake takes a full day to undo |
⚖️ The trade-off: TTL is the dial between agility and efficiency. Low TTL = fast changes, higher cost and latency. High TTL = fast lookups, slow changes.
The standard playbook before a planned migration: drop the TTL to 60 s at least 24–48 hours beforehand (so the old, long TTL has expired everywhere), do the migration, then raise it back. Doing this on the day of the migration is useless — resolvers are still holding the old long-TTL answer.
🚨 And here’s the part that matters most in interviews: even with a 60-second TTL, DNS failover is not reliable failover. Many resolvers ignore short TTLs. Java’s JVM historically cached DNS forever by default. Browsers pin connections. Some corporate resolvers enforce their own minimums. If your recovery plan depends on DNS propagating in 60 seconds, your recovery plan does not work. Use load balancers, anycast, or client-side retries for fast failover, and treat DNS as your slow, coarse-grained control.
Because DNS is a mapping under your control, you can return different answers to different people.
Round-robin DNS. Return multiple A records; clients pick one (usually the first, or randomly).
GeoDNS. Return the IP of the nearest region based on the resolver’s location. Karachi → Dubai region; Frankfurt → EU region. This is the standard way to do multi-region routing. Caveat: you see the resolver’s location, not the user’s — someone using 8.8.8.8 may appear to be somewhere else (mitigated by the EDNS Client Subnet extension).
Latency-based routing. The provider measures real-world latency and returns whichever region is actually fastest, which isn’t always the geographically nearest.
Weighted routing. 95% of answers point to v1, 5% to v2. A blunt but effective canary mechanism. → Deployment Strategies
Health-checked failover. The DNS provider probes your endpoints and stops returning unhealthy ones. Better than plain round-robin, still bounded by TTL and resolver behaviour.
Anycast — the technique that actually delivers fast global routing. The same IP address is announced from many datacenters worldwide, and BGP routes each user to the nearest one. No DNS change is involved, so failover is at network speed (seconds), not TTL speed. This is how 1.1.1.1, 8.8.8.8, and every serious CDN work.
DNS is a genuine single point of failure and has a long history of proving it. Some patterns worth knowing:
Mitigations to mention in interviews:
DNS isn’t just public. It’s the backbone of internal service discovery:
payments.default.svc.cluster.local) resolved by
CoreDNS. Your code calls a name; the cluster maps it to healthy pods.Practical consequence: never hard-code IPs in configuration. Use names, so instances can be
replaced without a deploy. Also, be aware of client-side DNS caching in your language runtime — the
JVM’s networkaddress.cache.ttl default has caused a memorable number of “we failed over but the
app kept hitting the dead host” incidents.
dig example.com # basic lookup — note the TTL in the answer
dig +trace example.com # walk the hierarchy yourself: root → TLD → authoritative
dig example.com NS # who's authoritative?
dig example.com MX # mail routing
dig -x 8.8.8.8 # reverse lookup
dig @1.1.1.1 example.com # ask a specific resolver
dig google.com # run twice, watch the TTL count down in the cached answer
Then look up a large site (dig +short netflix.com) and notice how many addresses come back, and
whether the answers change when you query from a different resolver. That’s GeoDNS in action.