DNS Record Types and What They Are For
A zone is a set of typed records — A/AAAA for addresses, CNAME for aliases, MX and TXT for mail and verification, NS and SOA for delegation and zone metadata, SRV and PTR for service discovery and reverse lookup — each with rules that bite (CNAME at the apex, chain cost) and a TTL you choose deliberately, especially before a migration.
The problem
engineer-atlas.dev has to say where the website is, where email goes, who is allowed to send mail as that domain, which servers are authoritative, how to find the reverse name of an address, and how long anyone may cache each of those facts. One record type cannot say all of that.Address records: A and AAAA
An A record maps a name to an IPv4 address; an AAAA record (four times 32 bits) maps it to an IPv6 address. A name may have several of each: a resolver returns all of them, typically rotating the order, and clients take the first or race them. That is round-robin DNS, the cheapest load distribution there is — and the crudest, because DNS has no idea whether the addresses are alive. Real failover needs health-checked DNS (Load Balancers: L4 vs L7 and CDNs: The Networking View are what usually sit behind an A record).
Modern clients ask for A and AAAA at the same time and try IPv6 first with a short head start (Happy Eyeballs, RFC 8305), so publishing a AAAA that points at a host whose IPv6 is broken produces "slow to connect" rather than "cannot connect": each connection waits out the IPv6 attempt before falling back. Publish AAAA only for addresses you monitor.
$ORIGIN engineer-atlas.dev.
$TTL 3600
@ IN SOA ns1.example-dns.net. hostmaster.engineer-atlas.dev. (
2026082501 ; serial
7200 ; refresh
900 ; retry
1209600 ; expire
300 ) ; minimum = negative-caching TTL
@ IN NS ns1.example-dns.net.
@ IN NS ns2.example-dns.net.
@ 300 IN A 203.0.113.10
@ 300 IN AAAA 2001:db8:1::10
www IN CNAME engineer-atlas.dev.
api 60 IN A 203.0.113.20
@ IN MX 10 mx1.example-mail.net.
@ IN MX 20 mx2.example-mail.net.
@ IN TXT "v=spf1 include:_spf.example-mail.net -all"
_sip._tcp IN SRV 10 60 5060 sip.engineer-atlas.dev.CNAME: an alias, and its rules
A CNAME says "this name is another name; look that one up instead". www.engineer-atlas.dev CNAME engineer-atlas.dev means the resolver restarts the query for the target and returns both records. It is how you point at something whose address you do not control — a CDN, a hosted platform, a load balancer whose IPs change — and it is the correct tool for that.
The rule that bites: a name with a CNAME may not have any other records. The RFCs say the alias replaces the name entirely, and resolvers and servers enforce it. The zone apex (engineer-atlas.dev itself) must carry SOA and NS records, so it cannot be a CNAME. That is why you cannot simply point a bare domain at your CDN, and why every DNS provider offers a non-standard workaround — ALIAS, ANAME, "CNAME flattening" — in which the provider resolves the target itself and synthesises A/AAAA answers. Those work but are provider-side magic: the resolver sees plain address records with the provider’s TTL.
CNAMEs chain: www → site.platform.example → lb-42.cdn.example → .... Each link the resolver does not already have cached is another lookup, potentially against a different authoritative server. Three links can be three extra round trips on a cold cache. Chains also hide who is actually answering, which matters when the last link is another company’s zone with its own TTL and outages. Keep chains short and know where they end.
- CNAME = alias. Resolver follows it and returns the chain.
- No other records at a CNAME name; no CNAME at the apex.
- ALIAS/ANAME/flattening are provider features, not DNS.
- Each uncached link in a chain is another lookup.
Mail and text: MX and TXT
MX records say where mail *for* a domain is delivered: a priority and a host name (never an IP — the host must have its own A/AAAA). Sending servers try the lowest priority first and fall back. A domain with no MX record has mail delivered to its A record, which is almost never what you want; a domain that should receive no mail should say so with a null MX (0 .).
TXT records started as free-form notes and became the universal extension point. SPF (v=spf1 …) lists which servers may send mail claiming to be from the domain. DKIM publishes the public key that signs outgoing mail, at selector._domainkey.domain. DMARC at _dmarc.domain tells receivers what to do when SPF and DKIM fail. And every SaaS provider proves you own a domain by asking you to publish a random token in a TXT record — which is why real zones accumulate dozens of google-site-verification= strings. TXT answers are the ones most likely to exceed the UDP size and trigger the TCP fallback described in DNS: Why Names Need a Distributed Database.
Delegation and zone metadata: NS and SOA
NS records name the servers authoritative for a zone. They appear twice: in the parent zone (the delegation the registry holds) and in the child zone itself, and they should agree. When they do not, resolvers that started from the parent reach one set of servers and resolvers that cached the child’s NS reach another — the split-brain of DNS Failure Modes: What Each One Looks Like. Changing DNS providers means changing NS records at the *registrar*, not just in the zone, and the old provider must keep serving until the old NS TTL (often two days) has expired everywhere.
The SOA record is the zone’s header: the primary server, the administrator contact (with the @ turned into a dot), a serial that secondaries compare to decide whether to re-transfer the zone, refresh/retry/expire timers for those secondaries, and the minimum field, which since RFC 2308 means the negative-caching TTL. If your zone’s SOA minimum is 86400, every typo and every not-yet-created name is remembered as non-existent for a day.
SRV and PTR
SRV records (_service._proto.name) map a service to a priority, a weight, a port and a target host. They are DNS’s built-in service discovery: SIP, XMPP, LDAP, Minecraft and Kubernetes headless services use them. Web browsers never did, which is why HTTP still needs the port in the URL. The newer SVCB/HTTPS records fill that gap for the web and also advertise HTTP/3 support and ECH keys.
PTR records go the other way: from an address to a name, in the special zones in-addr.arpa (IPv4, octets reversed: 10.113.0.203.in-addr.arpa) and ip6.arpa (nibbles reversed). They are delegated by whoever owns the address block — usually your cloud or hosting provider — so you cannot set them in your own zone. Mail servers reject or downgrade mail from addresses whose PTR does not match their forward name; and sshd, syslog and some databases do reverse lookups on connect, which is why a broken reverse DNS makes logins take exactly one resolver timeout.
| Type | Maps | Typical use | Watch out for |
|---|---|---|---|
| A / AAAA | name → IPv4 / IPv6 | the address of a host or service | AAAA to a broken IPv6 host = slow connects |
| CNAME | name → name | pointing at CDNs, platforms, load balancers | not at the apex; no other records; chain cost |
| MX | domain → mail host + priority | inbound email | target must be a name with A/AAAA |
| TXT | name → text | SPF, DKIM, DMARC, ownership verification | large answers → TCP fallback |
| NS | zone → name servers | delegation | parent and child must agree |
| SOA | zone → metadata | serial, secondary timers, negative TTL | minimum = how long NXDOMAIN is cached |
| SRV | service → host + port | SIP, LDAP, Kubernetes headless services | browsers ignore it |
| PTR | address → name | reverse lookup for mail and logging | owned by the address-block holder, not you |
Choosing TTLs, especially before a migration
A TTL is the maximum time the world may serve the old answer after you change it. High TTLs (hours, a day) mean fewer queries to your authoritative servers, faster resolution for clients, and resilience if your servers are briefly down. Low TTLs (30–300 s) mean fast failover and fast migrations at the cost of more queries and more exposure to authoritative outages. Records that a failover system flips should be low; records that never change (NS, MX) can be high.
The migration playbook follows from the countdown. If the record currently has a 1-hour TTL, lowering it to 60 seconds does nothing for the next hour — caches holding the old record keep it, with the *old* TTL, until it expires. So: lower the TTL at least one old-TTL period before the change (a day before, if the old TTL was a day), make the change, verify from several resolvers, keep the old destination serving until the *new* low TTL has expired plus a margin for misbehaving caches, then raise the TTL again. Skipping the first step is the most common reason a "five-minute migration" takes a day.
- Lower the TTL one old-TTL period before the change, not at the moment of the change.
- Keep the old endpoint alive until the new TTL has expired everywhere, with margin.
- Raise the TTL afterwards; a permanently low TTL is a permanently high query load.
Key points
- A/AAAA are addresses; multiple records mean round-robin without health checks.
- CNAME is an alias that replaces the name entirely — nothing else at that name, never at the apex; ALIAS/flattening are provider workarounds.
- MX names mail hosts by priority; TXT carries SPF/DKIM/DMARC and ownership tokens.
- NS records delegate and must match between parent and child; SOA holds the serial, secondary timers and the negative-caching TTL.
- SRV adds ports for service discovery; PTR is reverse lookup owned by the address holder.
- A TTL is a promise of maximum staleness; lower it one old-TTL period before any migration.
Why does this exist?
Mechanisms are answers to constraints. Open each question before reading the answer.
▸Why can’t the apex be a CNAME?
The apex must hold the SOA and NS records that define the zone, and a CNAME forbids any other record at its name. The RFC rule is what lets a resolver treat an alias as a complete replacement; the provider-side ALIAS is the workaround that keeps the rule and fakes the effect.
▸Why do MX and SRV point at names instead of addresses?
So that the mail or service host can be renumbered, dual-stacked or load-balanced by changing one A/AAAA record; the indirection is the whole point, and it is why a CNAME as an MX target is forbidden — it would be indirection on indirection with undefined behaviour.
▸Why separate record types at all instead of one "data" record?
Because clients ask typed questions and caches store typed answers: a mail server asks only for MX, a browser only for A/AAAA/HTTPS, and each can be cached with its own TTL and changed independently.
DNS record types
| Type | Name | Value | TTL (s) |
|---|---|---|---|
| A | example.com | 93.184.216.34 | |
| AAAA | example.com | 2606:2800:220:1:248:1893:25c8:1946 | |
| CNAME | www.example.com | example.com | |
| MX | example.com | 10 mail.example.com | |
| A | mail.example.com | 93.184.216.40 | |
| TXT | example.com | "v=spf1 mx -all" | |
| NS | example.com | ns1.example.com | |
| SRV | _sip._tcp.example.com | 10 60 5060 sip.example.com | |
| PTR | 34.216.184.93.in-addr.arpa | example.com |
Q: example.com A A: example.com 300 IN A 93.184.216.34
;; QUESTION www.example.com IN A www.example.com 3600 IN CNAME example.com ; alias, restart with target example.com 300 IN A 93.184.216.34
How it fails
What the failure looks like from inside real software.
- CNAME added at the apex through a permissive UI: some resolvers return the alias, some return SERVFAIL, and mail for the domain breaks because MX lookups now hit the CNAME rule.
- Migrating to a new DNS provider by changing the zone but not the NS records at the registrar: nothing changes for anyone, or worse, changes only for resolvers that cached the child NS.
- Publishing AAAA for a server whose IPv6 route is broken: every client with IPv6 waits out the Happy Eyeballs head start on each new connection; latency, not failure, so it is reported late.
- A five-link CNAME chain through two vendors: cold lookups take 100+ ms, and an outage at the last vendor takes down a name that has nothing to do with them in your zone.
- SOA minimum set to a day on a zone where services are created dynamically: every service is "not found" for 24 hours by any resolver that was asked too early.
- Cutting over with the TTL still at 3600 and the old server shut down immediately: an hour of a large fraction of users hitting a dead address.