Route 53 Alias vs CNAME Records: What Every AWS Engineer Must Know

When you provision an Application Load Balancer (ALB) and need to point your domain at it, you face an immediate DNS decision: use a standard CNAME or a Route 53 Alias record. This choice has real consequences — especially when your domain root (example.com) is involved.

TL;DR

Dimension CNAME Record Route 53 Alias Record
Zone Apex Support ❌ Not allowed (example.com) ✅ Fully supported
DNS Query Cost 💰 Charged per query ✅ Free for AWS targets
Resolution Hops 2 lookups (CNAME → A record) 1 lookup (resolves directly to IP)
Health Check Integration Manual / separate ✅ Native AWS health check awareness
Target Types Any hostname AWS resources only (ALB, CloudFront, S3, etc.)
TTL Control Configurable Managed by Route 53 (not user-configurable)

Core Takeaway: Always use an Alias record when pointing to an ALB in Route 53. It's faster, cheaper, and the only option that works at the zone apex.

The DNS Mechanics: Why CNAME Fails at the Zone Apex

The DNS specification (RFC 1912) prohibits a CNAME record from coexisting with other records at the same node. The zone apex (example.com) must have SOA and NS records. If you place a CNAME there, you violate the spec — and most DNS resolvers will either reject it or behave unpredictably.

This is the classic "naked domain" problem. Your users type example.com (not www.example.com), and you have no standards-compliant way to point that to an ALB hostname using a CNAME.

Analogy: Think of the zone apex like the lobby of a building. The building directory (SOA/NS records) must live in the lobby — you can't replace the lobby with a sign that says "go to another building" (CNAME). A Route 53 Alias record is like a smart receptionist who knows the other building's exact address and gives it directly to visitors, without replacing the lobby directory.

How Alias Records Work Internally

A Route 53 Alias record is not a standard DNS record type. It is a Route 53-proprietary extension that resolves at the Route 53 layer before the response leaves AWS infrastructure.

flowchart TD A["User queries example.com"] --> B["Route 53 Resolver"] B --> C{"Record Type?"} C -- "CNAME" --> D["Returns CNAME target hostname"] D --> E["Client performs 2nd lookup for ALB hostname"] E --> F["Returns ALB IP addresses"] C -- "Alias" --> G["Route 53 resolves ALB hostname internally"] G --> H["Returns ALB IP addresses directly"] F --> I["Client connects to ALB"] H --> I style G fill:#2e7d32,color:#fff style H fill:#2e7d32,color:#fff style D fill:#b71c1c,color:#fff style E fill:#b71c1c,color:#fff

With a CNAME, the resolver returns the ALB's DNS name (e.g., my-alb-123456.us-east-1.elb.amazonaws.com), and the client must perform a second DNS lookup to resolve that to an IP. With an Alias, Route 53 performs that resolution internally and returns the final A record directly — one round trip, not two.

Architecture: Domain to ALB via Alias Record

Browser / ClientRoute 53Application Load BalancerTarget GroupHosted Zone (example.com)Alias Record (A)HTTPS:443EC2 Instance AEC2 Instance B resolvesDNS query example.comresolves ALB dns_name internallyroutes trafficroutes trafficHTTPS request (direct to IP)

Cost Impact

Route 53 charges $0.40 per million queries for standard records. Alias records pointing to AWS resources (ALB, CloudFront, Elastic Beanstalk, S3 website endpoints, API Gateway) are free. At scale — millions of DNS queries per day — this difference is material. A high-traffic site saving 10M queries/day avoids ~$120/month in DNS costs alone.

Implementation: Terraform

The following Terraform snippet creates an Alias record pointing example.com to an ALB. Note the alias block — there is no ttl argument (Route 53 manages it).

🔽 [Click to expand] Terraform: Route 53 Alias Record → ALB

# Assumes you have an ALB resource: aws_lb.main
# and a hosted zone: aws_route53_zone.primary

resource "aws_route53_record" "apex_alias" {
  zone_id = aws_route53_zone.primary.zone_id
  name    = "example.com"   # Zone apex — impossible with CNAME
  type    = "A"

  alias {
    name                   = aws_lb.main.dns_name
    zone_id                = aws_lb.main.zone_id  # ALB's hosted zone ID, NOT your zone
    evaluate_target_health = true  # Route 53 respects ALB health checks
  }
}

# Optional: www subdomain — also use Alias for consistency
resource "aws_route53_record" "www_alias" {
  zone_id = aws_route53_zone.primary.zone_id
  name    = "www.example.com"
  type    = "A"

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

Critical detail: The zone_id inside the alias block is the ALB's canonical hosted zone ID (e.g., Z35SXDOTRQ7X7K for us-east-1), not your domain's hosted zone. AWS publishes these per-region per-service in their documentation.

When a CNAME Is Still Acceptable

CNAMEs remain valid for subdomains pointing to non-AWS targets — for example, status.example.com CNAME statuspage.io. If your target is outside AWS, Alias records are not an option. For all AWS-native targets at any level, prefer Alias.

Wrap-up & Next Steps

Use a Route 53 Alias record whenever pointing any domain — especially the zone apex — to an AWS resource like an ALB: it's the only RFC-compliant option at example.com, resolves in a single hop, costs nothing, and inherits native health check awareness.

📖 Next Steps: Review the official AWS documentation on Choosing Between Alias and Non-Alias Records and the ELB endpoints and quotas page for the correct ALB zone IDs per region.

Glossary

  • Zone Apex: The root of a DNS zone (e.g., example.com), where SOA and NS records are mandatory and CNAME records are prohibited by RFC.
  • CNAME (Canonical Name): A DNS record that maps one hostname to another hostname, requiring a second resolution step by the client.
  • Route 53 Alias Record: A Route 53-proprietary DNS extension that maps a domain directly to an AWS resource's IP(s), resolved internally before the response is returned.
  • evaluate_target_health: An Alias record flag that instructs Route 53 to propagate the health status of the target AWS resource into DNS routing decisions.
  • ALB Canonical Hosted Zone ID: A fixed AWS-assigned zone identifier for each ALB per region, required in the Alias record configuration to enable proper DNS delegation.

Comments

Popular posts from this blog

EC2 No Internet Access in Custom VPC: Attaching an Internet Gateway and Fixing Route Tables

Lambda Infinite Loop with S3: How to Break the Recursive Trigger Cycle

IAM User vs. IAM Role: Why Your EC2 Instance Should Never Use a User