Understanding DNS Record Types
DNS record types are the routing primitives that decide where every request, email, and service lookup for your domain ultimately lands. This guide maps each record type to its production behavior on the wire, the provider-specific quirks you hit on Cloudflare, AWS Route 53, and GCP Cloud DNS, and the operational procedures that keep cutovers safe. For broader architectural context, work through the DNS Fundamentals & Advanced Record Configuration pillar before you push changes into a live zone.
Key implementation priorities:
- Correct record selection for cloud and edge environments, including apex versus subdomain constraints
- Platform-specific wire behavior across Cloudflare, AWS Route 53, and GCP Cloud DNS
- Deployment and verification procedures for A, AAAA, CNAME/ALIAS, MX, TXT, and SRV records
- TTL, caching, and propagation implications during CDN migrations and origin shifts
Core DNS record types and architecture mapping
DNS records are the routing layer for everything else in your stack. The record type you choose for a given hostname determines latency, failover behavior, CDN origin shielding, and whether email and service discovery even function. Each type answers a specific question type (qtype) and is returned only when the resolver is asked for that type.
| Record | Primary function | DevOps / edge use case |
|---|---|---|
| A / AAAA | Direct IPv4 / IPv6 routing | Origin server mapping, dual-stack load balancing |
| CNAME | Domain aliasing | CDN integration, multi-CDN routing, subdomain delegation |
| MX | Mail exchange routing | Third-party email gateways, SaaS mailbox routing |
| TXT | Arbitrary text data | SPF/DKIM/DMARC, domain ownership verification |
| SRV | Service discovery | Microservice endpoints, SIP/XMPP, Kubernetes mesh routing |
| NS | Delegation | Subzone delegation, registrar glue |
| CAA | Certificate authority authorization | Restricting which CAs may issue TLS certs |
A critical mental model: a resolver never “follows” record types it was not asked for, except for the implicit CNAME chase. When you query A, an authoritative server that holds a CNAME for that name returns the CNAME plus, if it is authoritative for the target, the resolved A record. This single behavior explains most apex and aliasing edge cases later in this guide. The first mention of each concept that has its own guide links there: deep dives on aliasing live in CNAME Flattening Explained, mail and service routing in Advanced SRV & MX Routing, and signing in DNSSEC Operational Management.
Two structural records frame everything else. The SOA (Start of Authority) record at the apex carries the zone serial, refresh, retry, expire, and minimum (negative-cache) timers; the minimum field sets how long resolvers cache an NXDOMAIN, which is why a typo in a name can “stick” long after you fix the zone. NS records at the apex declare which servers are authoritative, and matching NS plus glue records at the parent (your registrar) complete the delegation. If the apex NS set and the registrar’s NS set disagree, you get a lame delegation: intermittent SERVFAIL that depends on which nameserver a resolver happened to ask. Confirm both sides match before debugging any individual record type.
Always validate authoritative responses against the authoritative nameserver directly, bypassing local and recursive caches.
dig @ns1.example.com example.com A +short
Expected output:
203.0.113.10
nslookup -type=MX example.com 8.8.8.8
Expected output:
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
example.com mail exchanger = 10 mail.example.com.
A and AAAA records: IPv4/IPv6 dual-stack implementation
Dual-stack DNS requires precise A and AAAA pairing. Modern clients use the Happy Eyeballs algorithm (RFC 8305) to race IPv4 and IPv6 connections and commit to the first successful TCP handshake. A misconfigured AAAA record that points at an unreachable IPv6 path inflates connection latency or causes timeouts on networks where the fallback is slow. The rule is simple: never publish an AAAA record until the IPv6 path is reachable and load tested end to end.
Before you lower TTLs for IP rotation or a blue/green cutover, confirm IPv6 reachability and align the timing with Mastering TTL Strategies so resolvers are not still holding stale answers when you flip the origin. For the full subnet-validation and migration procedure, follow How to Configure A vs AAAA Records for IPv6 Migration.
A single hostname can hold multiple A (or AAAA) records, and authoritative servers typically rotate the order on each response (round-robin DNS). This is the cheapest possible spread of load, but it is not load balancing: there are no health checks, so a dead IP keeps getting handed out until you remove the record or a health-aware layer (Route 53 health checks, Cloudflare load balancing) withdraws it. Treat multi-A round-robin as coarse distribution, never as failover. When you do need failover at the DNS layer, prefer ALIAS-with-health-check or a dedicated load balancer rather than juggling raw A records by hand.
Cloudflare
Cloudflare proxies (orange-cloud) A and AAAA records through its edge, returning Cloudflare anycast IPs rather than your origin IP. Add both records and toggle the proxy; AAAA is served automatically even if clients only have IPv4 because Cloudflare terminates at the edge.
# Create proxied A and AAAA records via the Cloudflare API
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
--data '{"type":"A","name":"app","content":"203.0.113.10","ttl":1,"proxied":true}'
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
--data '{"type":"AAAA","name":"app","content":"2001:db8::10","ttl":1,"proxied":true}'
AWS Route 53
Route 53 uses ALIAS records for AWS-native dual-stack targets (an A alias and an AAAA alias both pointing at the same ELB or CloudFront distribution). For raw IPs, publish standard A and AAAA records with an explicit TTL.
{
"Comment": "Dual-stack ALIAS to an ALB",
"Changes": [
{"Action":"UPSERT","ResourceRecordSet":{"Name":"app.example.com","Type":"A",
"AliasTarget":{"HostedZoneId":"Z35SXDOTRQ7X7K","DNSName":"dualstack.my-alb-123.us-east-1.elb.amazonaws.com","EvaluateTargetHealth":true}}},
{"Action":"UPSERT","ResourceRecordSet":{"Name":"app.example.com","Type":"AAAA",
"AliasTarget":{"HostedZoneId":"Z35SXDOTRQ7X7K","DNSName":"dualstack.my-alb-123.us-east-1.elb.amazonaws.com","EvaluateTargetHealth":true}}}
]
}
GCP Cloud DNS / Fastly
GCP Cloud DNS treats A and AAAA as plain resource record sets; pair them with a low TTL during migrations. Fastly fronts origins with anycast and expects you to CNAME (or use its apex A records) to the service domain.
gcloud dns record-sets create app.example.com. --zone=prod-zone \
--type=A --ttl=300 --rrdatas=203.0.113.10
gcloud dns record-sets create app.example.com. --zone=prod-zone \
--type=AAAA --ttl=300 --rrdatas=2001:db8::10
CNAME, ALIAS, and ANAME: edge routing and CDN integration
CNAME records enable flexible aliasing but violate RFC 1034 when placed at the zone apex, because the apex must also hold NS and SOA records and a CNAME forbids any sibling records at the same name. The result is broken NS and MX resolution and SERVFAIL for mail and authoritative queries. Cloud providers solve this with flattening or virtual-record mechanisms that resolve the alias at the authoritative layer and return A/AAAA instead of CNAME.
| Provider | Mechanism | Wire behavior | Failover / notes |
|---|---|---|---|
| Cloudflare | CNAME Flattening | Resolves CNAME to IP at query time, returns A/AAAA | Automatic at apex; follows target TTL, re-resolves on expiry |
| AWS Route 53 | ALIAS | Returns target’s A/AAAA; no extra lookup billed | EvaluateTargetHealth enables health-based failover |
| NS1 / DNSMadeEasy | ANAME | Virtual CNAME resolved at authoritative level | Resolver-side TTL honored; target re-checked server-side |
| Azure DNS | Alias record set | Returns A/AAAA for Azure resources | Tracks target lifecycle, auto-updates on resource change |
When migrating CDNs or shifting edge routing, align TTL adjustments with Mastering TTL Strategies to prevent cache thrashing. ALIAS or flattening is mandatory for SaaS custom domains that require apex routing; plain CNAMEs remain optimal for subdomains where RFC compliance is guaranteed.
Cloudflare
# Apex CNAME that Cloudflare flattens to A/AAAA automatically
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
--data '{"type":"CNAME","name":"@","content":"app-12345.cdn-provider.net","ttl":1,"proxied":true}'
AWS Route 53
aws route53 change-resource-record-sets --hosted-zone-id "$HOSTED_ZONE" \
--change-batch '{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{
"Name":"example.com","Type":"A","AliasTarget":{
"HostedZoneId":"Z2FDTNDATAQYW2","DNSName":"d111abcdef8.cloudfront.net",
"EvaluateTargetHealth":false}}}]}'
GCP Cloud DNS / Fastly
GCP Cloud DNS has no native apex flattening, so apex hosts must use A/AAAA records pointed at static anycast IPs (Fastly publishes a documented set) while subdomains use CNAME.
gcloud dns record-sets create www.example.com. --zone=prod-zone \
--type=CNAME --ttl=300 --rrdatas=app-12345.cdn-provider.net.
Verification workflow:
curl -sI https://app.example.com | head -n 3
Expected output:
HTTP/2 200
server: cloudflare
cf-ray: 7a8b9c0d1e2f3g4h-SJC
If the server header matches your CDN but the resolved origin IP changes unexpectedly, inspect the flattening toggle. Disable flattening temporarily to read the raw authoritative CNAME during troubleshooting.
TXT, MX, and SRV: service verification and routing
TXT, MX, and SRV records handle policy verification, mail routing, and internal discovery. TXT records carry SPF, DKIM, and DMARC policies but require strict formatting: a single character-string cannot exceed 255 bytes, so long DKIM public keys must be split into multiple quoted strings that resolvers concatenate. MX routing relies on integer preference values where lower numbers win; assign a secondary gateway a preference of 20 or higher for fallback. SRV records expose priority, weight, port, and target for service discovery in microservice meshes.
For the complete mail-routing and discovery procedures, including DKIM key generation and DMARC enforcement, see Advanced SRV & MX Routing. Hybrid DNS/CDN setups sometimes chain verification records through aliases; CNAME Flattening Explained covers how recursive resolvers handle those chains.
Configuration examples (BIND zone syntax):
; SPF authorization with soft-fail for monitoring
@ IN TXT "v=spf1 include:_spf.saas-provider.com ~all"
; DKIM split across 255-byte strings (resolvers concatenate)
selector1._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArandompublickeypart1"
"morekeydatapart2continuingpastthe255bytestringboundaryhere" )
; SRV for internal API discovery (priority weight port target)
_api._tcp IN SRV 10 5 8080 api.internal.svc.cluster.local.
; MX routing with primary and fallback
@ IN MX 10 mail-primary.example.com.
@ IN MX 20 mail-fallback.example.com.
Validate SPF syntax before publishing:
dig +short TXT example.com | grep "v=spf1"
Expected output:
"v=spf1 include:_spf.saas-provider.com ~all"
Two SPF gotchas bite teams repeatedly. First, SPF permits at most ten DNS-resolving mechanisms (include, a, mx, ptr, exists); exceeding the limit yields a permerror and many receivers then treat the message as unauthenticated. Flatten nested includes or consolidate senders to stay under the cap. Second, a domain must publish exactly one SPF TXT record; two v=spf1 strings is also a permerror. SRV records carry their own trap: the target must be a real hostname with an A/AAAA record, never an IP and never a CNAME, and a target of . explicitly advertises that the service is not available at this domain. MX has the same hostname rule, so pointing an MX at a CDN-fronted CNAME silently breaks mail delivery.
Operational procedure: deploying and verifying a record change
Follow this sequence for any production record change to keep the blast radius small.
- Read the current record and its TTL:
dig @<authoritative-ns> <name> <type>and note the TTL. - If the TTL is high, lower it (for example to 300) and wait the old TTL window so resolvers expire their cache before the real change.
- Stage the new value behind health checks (ALIAS
EvaluateTargetHealth, Route 53 health checks, or Cloudflare load balancer monitors). - Apply the change through your provider API or infrastructure-as-code, never by hand-editing a live zone.
- Verify against multiple public resolvers, not just one:
for r in 1.1.1.1 8.8.8.8 9.9.9.9; do
echo "== $r =="; dig @$r app.example.com A +short
done
- Confirm the authoritative answer and TTL match what you published.
- Once stable, restore a normal TTL (3600+) to reduce query load and cost.
TTL, caching, and propagation implications
“Propagation” is a misnomer: there is no global push. A change is visible the instant you publish it authoritatively, but recursive resolvers keep serving the previous answer until the TTL they cached expires. That is why lowering TTLs 24-48 hours before a cutover is the single most effective propagation control. Some public resolvers clamp very low TTLs to a minimum floor and a few ignore them entirely, so plan for a slow trickle of stragglers and keep the old origin warm.
For ALIAS and flattened records, two TTLs matter: the TTL the resolver caches for the apex answer, and the upstream TTL the provider honors when re-resolving the target. Cloudflare flattening follows the target’s TTL; Route 53 ALIAS re-evaluates target health continuously and does not bill the second lookup. Detailed cache-window math and rollout timing live in Mastering TTL Strategies.
Negative caching deserves its own attention because it bites during rollouts. If a client queries a name before you create it, the resolver caches the NXDOMAIN for the SOA minimum field (commonly 300 to 3600 seconds), so the record appears “not to propagate” even though it is published. Keep the SOA minimum low during active migrations, and avoid querying not-yet-created names from monitoring systems whose resolvers you cannot flush. A practical pattern is to create the record first with a low TTL, confirm it resolves on every public resolver you care about, and only then send traffic, rather than wiring traffic to a name that does not yet exist.
Troubleshooting, validation, and rollback
Misconfigured records surface as NXDOMAIN (the name does not exist) or SERVFAIL (the authoritative chain or DNSSEC validation failed). Use dig +trace to walk the full delegation from the root and pinpoint where it breaks.
dig +trace example.com AAAA
Expected output (abbreviated):
; <<>> DiG 9.16.1 <<>> +trace example.com AAAA
;; global options: +cmd
. 518400 IN NS a.root-servers.net.
...
example.com. 300 IN AAAA 2001:db8::10
Platform-specific debugging:
- Cloudflare: Inspect the DNS analytics tab for query spikes; enable “Always Online” to serve cached pages during origin failures.
- Route 53: Drive failover with health checks and watch the
HealthCheckStatusandDNSQueriesCloudWatch metrics. - GCP Cloud DNS: Enable DNSSEC on the managed zone and validate from a VPC resolver to rule out cache poisoning.
Run resolvectl status (or systemd-resolve --status) on Linux hosts to confirm local resolver behavior, and parse edge/CDN access logs for 502 or 504 spikes, which often correlate with DNS resolution timeouts during an origin shift.
A reliable triage order saves time. First classify the failure: NXDOMAIN means the name genuinely is not in the zone (check for a missing record or a typo), while SERVFAIL means the authoritative chain answered with an error or failed DNSSEC validation. Run the same query with +cd (checking disabled); if it succeeds only with +cd, the problem is a signing or DS mismatch, not the record. Next, query the authoritative server directly with dig @<ns> <name> <type> to separate authoritative truth from resolver cache. Then compare the apex NS set returned by the zone against the registrar’s delegation to rule out a lame delegation. Finally, read the answer, authority, and additional sections together: a CNAME in the answer with no resolved A beneath it usually means the target lives in a zone your authoritative server does not serve, so the resolver must chase it separately.
# Distinguish a DNSSEC failure from a record error
dig example.com A +dnssec # SERVFAIL here ...
dig example.com A +cd # ... but success here points at DNSSEC
Rollback strategy: Keep the previous A/AAAA (or ALIAS target) documented and a script ready to re-UPSERT it. Because you lowered the TTL before the change, resolvers will pick the reverted answer within the short cache window. If a new origin fails health checks, revert first and diagnose second. SERVFAIL appearing only after a signing change points at DNSSEC Operational Management rather than the record itself.
Edge cases and gotchas
- CNAME at the zone apex violates RFC 1034 and breaks NS/MX, causing SERVFAIL. Use ALIAS, ANAME, or CNAME flattening instead.
- A CNAME cannot coexist with any other record at the same name (no MX, TXT, or DNSSEC RRSIG siblings). This is the most common cause of “my MX disappeared.”
- TXT strings cap at 255 bytes each; split long SPF and DKIM values into multiple quoted strings rather than one oversized string.
- Dangling CNAMEs pointing at deprovisioned cloud resources are a subdomain-takeover risk; audit and remove them.
- Mixed IPv4/IPv6 resolution on asymmetric networks causes client timeouts; validate IPv6 end to end before publishing AAAA.
- Wildcard records (
*) do not match the apex or already-defined names and never expand inside the CNAME chain; test them explicitly. - CAA records gate certificate issuance: a missing or wrong CAA blocks a CA from issuing, surfacing as a TLS renewal failure, not a DNS error.
| Scenario | Impact | Mitigation |
|---|---|---|
| CNAME at zone apex | Breaks MX/NS, SERVFAIL for mail and authoritative queries | Use ALIAS/ANAME or CNAME flattening |
| TXT string exceeds 255 bytes | SPF/DKIM validation fails, deliverability drops | Split into multiple quoted strings: "part1" "part2" |
| Low TTL during migration | Cache thrash, resolver load, brief origin exposure | Lower TTL 48h prior, pre-warm CDN, drain at the edge |
| Mixed IPv4/IPv6 on asymmetric networks | Client timeouts, slow IPv4 fallback | Validate IPv6 end to end, monitor dual-stack metrics |
Frequently Asked Questions
Can I use a CNAME record at the root domain (apex)? No. RFC 1034 forbids a CNAME coexisting with the NS and SOA records that the apex must carry, so it breaks MX and NS resolution. Use provider ALIAS, ANAME, or CNAME flattening to get the same routing without the breakage.
How does DNS record selection affect CDN edge routing? CNAME and ALIAS records send traffic to CDN edge nodes that anycast to the nearest POP, while A/AAAA records point straight at an origin. Proper aliasing is what enables edge routing, geo load balancing, and origin shielding rather than exposing the origin IP directly.
What is the maximum length of a TXT record? Each character-string is capped at 255 bytes, but a single TXT record may contain several strings. For long SPF or DKIM values, split into multiple quoted segments and resolvers concatenate them automatically.
Why do DNS changes sometimes take hours to take effect? Recursive resolvers cache the prior answer for the duration of its TTL, and some clamp or ignore very low TTLs. Lower the TTL 24-48 hours before the change and keep the old origin live until the last stragglers expire.