Route 53 Record Types: A, AAAA, CNAME, Alias, MX, TXT, and When to Use Each

2 min readCloud Infrastructure

DNS record types serve different purposes. A/AAAA map names to IP addresses. CNAME maps one name to another. Route 53 Alias records extend A/AAAA to point at AWS resources without a CNAME restriction. Understanding when to use Alias vs CNAME — and why CNAME at zone apex is prohibited — prevents common DNS configuration mistakes.

awsroute53dns

DNS record types and their purposes

| Record type | What it maps | Example | |---|---|---| | A | Name → IPv4 address | api.example.com → 203.0.113.10 | | AAAA | Name → IPv6 address | api.example.com → 2001:db8::1 | | CNAME | Name → another name | www.example.com → api.example.com | | Alias | Name → AWS resource DNS name | example.com → d1234.cloudfront.net | | MX | Domain → mail server | example.com → mail.example.com (priority 10) | | TXT | Name → arbitrary text | SPF records, domain verification tokens | | NS | Zone → nameservers | Delegated at domain registration | | SOA | Zone → authority info | Auto-created by Route 53 |

CNAME restriction at zone apex and why Alias records exist

ConceptRoute 53 / DNS

A CNAME record cannot exist at the zone apex (the root domain, e.g., example.com). This is a DNS protocol rule — a name with a CNAME cannot have any other records, including the SOA and NS records required at the apex. Route 53 Alias records solve this by functioning like CNAMEs (pointing to a DNS name) while being stored as A/AAAA records that can coexist with SOA and NS.

Prerequisites

  • DNS hierarchy and zones
  • A vs CNAME records
  • AWS load balancers and CloudFront

Key Points

  • CNAME at apex (example.com) is prohibited by RFC 1034. Use Alias instead.
  • Alias records are Route 53-specific — they're stored as A/AAAA but resolve to the target resource's IPs.
  • Alias targets: ALB, NLB, CloudFront, S3 website, API Gateway, Elastic Beanstalk, other Route 53 records.
  • Alias records have no charge for queries to AWS resources. CNAME queries are charged.

A and AAAA: direct IP mapping

# A record: IPv4
resource "aws_route53_record" "app" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "A"
  ttl     = 300
  records = ["203.0.113.10", "203.0.113.11"]  # multiple for round-robin
}

# AAAA record: IPv6
resource "aws_route53_record" "app_v6" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "AAAA"
  ttl     = 300
  records = ["2001:db8::10"]
}

A records with multiple values return all IPs in a shuffled order. DNS clients typically use the first IP in the list. This is not reliable load balancing — use an ALB or NLB for real load balancing.

CNAME: canonical name aliases

resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "www.example.com"
  type    = "CNAME"
  ttl     = 300
  records = ["api.example.com"]  # or external domain
}

CNAME limitations:

  • Cannot be at zone apex (example.com)
  • Creates an additional DNS lookup (two queries instead of one)
  • Cannot coexist with other records for the same name (adding MX to www.example.com when www is a CNAME violates DNS standards)

Alias records: CNAMEs for AWS resources

# Alias to ALB — works at zone apex
resource "aws_route53_record" "apex" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "example.com"         # zone apex
  type    = "A"

  alias {
    name                   = aws_lb.main.dns_name
    zone_id                = aws_lb.main.zone_id
    evaluate_target_health = true
  }
}

# Alias to CloudFront
resource "aws_route53_record" "cdn" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "example.com"
  type    = "A"

  alias {
    name                   = aws_cloudfront_distribution.main.domain_name
    zone_id                = aws_cloudfront_distribution.main.hosted_zone_id
    evaluate_target_health = false  # CloudFront is always highly available
  }
}

evaluate_target_health = true causes Route 53 to check if the alias target is healthy before returning it in DNS responses. For ALBs, this means Route 53 considers the ALB health (not just whether the DNS name resolves) when responding to queries.

MX and TXT: email and domain verification

# MX records for email
resource "aws_route53_record" "mx" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "example.com"
  type    = "MX"
  ttl     = 3600
  records = [
    "10 mail.example.com",    # priority 10 = primary
    "20 mail2.example.com"    # priority 20 = fallback
  ]
}

# TXT records for SPF and domain verification
resource "aws_route53_record" "spf" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "example.com"
  type    = "TXT"
  ttl     = 300
  records = [
    "v=spf1 include:_spf.google.com include:amazonses.com -all",
    "google-site-verification=abcdef1234"  # multiple TXT values supported
  ]
}

SPF (Sender Policy Framework) prevents email spoofing by declaring which servers can send email for your domain. DMARC and DKIM are also configured via TXT records.

📝NS records and subdomain delegation

NS (Name Server) records delegate a subdomain to a different Route 53 hosted zone or to an external DNS provider:

# Delegate staging.example.com to a separate hosted zone
resource "aws_route53_record" "staging_ns" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "staging.example.com"
  type    = "NS"
  ttl     = 300
  records = aws_route53_zone.staging.name_servers
}

After this, Route 53 answers queries for *.staging.example.com from the staging hosted zone, not the main zone. This pattern gives separate teams or environments independent DNS management — the staging team can add/remove records in their zone without affecting the main zone.

NS delegation requires that the delegated zone exists and has authoritative name servers before you create the NS record in the parent zone. Creating the NS record in the parent zone with name servers that don't yet exist causes NXDOMAIN responses for the delegated subdomain.

TTL: controlling cache duration

TTL (Time To Live) controls how long resolvers cache a record. Shorter TTL means faster propagation of changes; longer TTL means fewer DNS queries and lower cost.

Practical guidance:

  • Low TTL (60-300s): for records that change frequently or when planning a migration. Use 60s in the hours before a cutover, then restore after.
  • Medium TTL (300-3600s): standard for most records. Good balance of freshness and caching.
  • Long TTL (86400s, 1 day): for rarely-changed records (MX, NS, static infrastructure). Reduces DNS query volume.

During a migration, lower the TTL well in advance (wait at least one current TTL period after lowering before making the change), make the change, then raise the TTL again after propagation confirms.

You want to point your root domain (example.com) to a CloudFront distribution. You create a CNAME record for example.com pointing to d1234.cloudfront.net. DNS queries to example.com fail with SERVFAIL. What is wrong?

easy

Route 53 hosted zone for example.com already has NS and SOA records at the apex. The CNAME was created successfully in the Route 53 console.

  • ACloudFront doesn't support CNAME records from Route 53
    Incorrect.CloudFront supports both CNAME and Alias records. The problem is using CNAME at the zone apex, not a CloudFront restriction.
  • BA CNAME at the zone apex (example.com) is prohibited by DNS standards — it conflicts with the required NS and SOA records at the apex. Route 53 may accept the creation but DNS resolvers return SERVFAIL
    Correct!RFC 1034 prohibits CNAME records that coexist with other record types. The zone apex must have NS and SOA records. A CNAME at example.com would conflict with these — DNS resolvers treat this as an invalid configuration and return SERVFAIL. Fix: use a Route 53 Alias A record pointing to the CloudFront distribution. Alias records are stored as A records (compatible with NS/SOA at apex) but resolve to the CloudFront distribution's IPs.
  • CThe CloudFront distribution must have example.com as an alternate domain name configured
    Incorrect.This is also required (CloudFront must be configured with the custom domain), but the immediate cause of SERVFAIL is the CNAME at zone apex issue.
  • DCNAME records require a trailing dot (d1234.cloudfront.net.)
    Incorrect.Route 53 handles trailing dots transparently. This isn't the cause of SERVFAIL.

Hint:What records are required at the zone apex, and why does a CNAME there cause problems?