Skip to main content

AWS Route 53 Guide: When to Use Alias vs. CNAME Records

 You have deployed a scalable architecture using an Application Load Balancer (ALB) or a CloudFront distribution. The infrastructure is solid. Now, you simply need to point your root domain (e.g., example.com) to the AWS resource.

You attempt to create a standard CNAME record in Route 53, but the operation fails. Alternatively, if you are using a third-party DNS provider, the record simply refuses to save.

This is not a bug in AWS. It is a fundamental constraint of the DNS protocol itself.

This guide details why the "Zone Apex" problem exists, how Route 53 Alias records bypass this limitation, and provides the production-ready Terraform code required to implement the solution correctly.

The Architectural Constraint: RFC 1034

To understand the solution, you must understand the strict rules governing the Domain Name System (DNS). The issue stems from the original DNS specification, specifically RFC 1034 section 3.6.2.

The Zone Apex Conflict

The root of a domain, such as example.com (without www), is referred to as the Zone Apex.

According to DNS standards, a specific domain name cannot have both a CNAME record and any other type of record. However, the Zone Apex must contain at least two specific record types to function:

  1. NS (Name Server): Defines which servers answer for the domain.
  2. SOA (Start of Authority): Defines administrative information about the zone.

Because the Zone Apex requires NS and SOA records, and a CNAME record cannot coexist with other records, you cannot technically create a CNAME at the root domain.

The Consequence

If you try to map example.com -> my-loadbalancer-123.us-east-1.elb.amazonaws.com using a CNAME, the DNS protocol rejects it. This forces developers to use subdomains (like www.example.com) for CNAMEs, leaving the root domain stranded.

The Solution: Route 53 Alias Records

AWS circumvented this protocol limitation by introducing Alias Records.

An Alias record is not a standard DNS record type like A, AAAA, or CNAME. It is an internal Route 53 pointer. When a DNS query hits Route 53 for an Alias record, Route 53 internally resolves the target AWS resource (like an ALB) to its current IP addresses and returns those IPs to the client as standard A (IPv4) or AAAA (IPv6) records.

To the outside world (DNS resolvers), it looks like a standard A-record. Internally, it behaves like a dynamic CNAME that tracks the changing IPs of AWS infrastructure.

Key Benefits of Alias Records

  1. Root Domain Support: Allows mapping example.com directly to AWS resources.
  2. Free Queries: Queries to Alias records that point to AWS resources (CloudFront, Elastic Beanstalk, ELB, S3) are generally free of charge.
  3. Faster Resolution: Unlike a CNAME, which requires the recursive resolver to perform a second lookup for the target domain, an Alias returns the IP immediately.

Implementation: Terraform Infrastructure as Code

While you can click through the AWS Console to set this up, production environments require reproducibility. Below is the modern Terraform (HCL) configuration to map a Zone Apex to an Application Load Balancer.

Prerequisites

  • An existing Hosted Zone for your domain.
  • An existing Application Load Balancer.

The Terraform Configuration

provider "aws" {
  region = "us-east-1"
}

# 1. Reference the existing Hosted Zone
data "aws_route53_zone" "main" {
  name         = "example.com."
  private_zone = false
}

# 2. Reference the existing ALB (assuming it exists)
resource "aws_lb" "app_lb" {
  name               = "production-app-lb"
  internal           = false
  load_balancer_type = "application"
  subnets            = ["subnet-abc12345", "subnet-def67890"] 
  # Security groups and other config omitted for brevity
}

# 3. The IPv4 Alias Record (A Record)
resource "aws_route53_record" "apex_ipv4" {
  zone_id = data.aws_route53_zone.main.zone_id
  name    = "example.com" # The Zone Apex
  type    = "A"

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

# 4. The IPv6 Alias Record (AAAA Record) - Highly Recommended
resource "aws_route53_record" "apex_ipv6" {
  zone_id = data.aws_route53_zone.main.zone_id
  name    = "example.com"
  type    = "AAAA"

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

Critical Configuration Details

type = "A" Notice that even though we are pointing to a domain name (the ALB DNS name), the record type is A. This is required for Alias records. Route 53 will dynamically resolve the ALB's DNS to an IP address at query time.

evaluate_target_health = true This is a powerful feature specific to Aliases. If your Load Balancer becomes unhealthy (fails health checks), Route 53 detects this. If you have a failover routing policy (e.g., active-passive), Route 53 will stop serving the IP of the unhealthy resource. Standard CNAMEs cannot do this.

Deep Dive: Alias vs. CNAME Comparison

Use this decision matrix to determine the correct record type for your infrastructure.

FeatureAlias RecordCNAME Record
Zone Apex SupportYes (example.com)No (Only subdomains like www)
TargetAWS Resources (ALB, S3, CloudFront)Any Domain Name
PricingFree for AWS targetsStandard DNS query rates
PerformanceFaster (Single Lookup)Slower (Recursive Lookup)
DNS ProtocolProprietary (AWS Internal)RFC Standard
Health ChecksCan inherit target healthRequires separate health check

Common Pitfalls and Edge Cases

1. The "Hosted Zone ID" Confusion

When creating an Alias via Terraform or the CLI, you must provide a zone_id in the alias block.

Crucial: This is not your domain's Hosted Zone ID. It is the canonical Hosted Zone ID of the AWS service you are pointing to.

  • For CloudFront, the Zone ID is always Z2FDTNDATAQYW2 (a fixed global constant).
  • For ALB/ELB, the Zone ID varies by AWS Region. Terraform's aws_lb resource exports this attribute automatically as aws_lb.example.zone_id, so always reference the resource attribute rather than hardcoding strings.

2. Pointing to Non-AWS Resources

You cannot use an Alias record to point the Zone Apex to a non-AWS resource (like a Heroku app or a Vercel deployment). Alias records only work because AWS owns the internal mapping logic for their services.

If you must point a root domain to a non-AWS provider, you are usually forced to use a third-party DNS provider that supports "CNAME Flattening" or "ANAME" records (such as Cloudflare), or use an S3 redirect bucket to bounce root traffic to www.

3. TTL (Time To Live) Management

You cannot set a TTL on an Alias record. Because the Alias record points to an AWS resource, Route 53 respects the TTL set by the target resource (e.g., the ALB's internal DNS TTL, which is usually 60 seconds). This ensures that if AWS scales your load balancer and changes the IPs, your DNS updates almost instantly.

Summary

If you are operating within the AWS ecosystem, always prefer Alias records over CNAMEs, regardless of whether you are configuring the root domain or a subdomain.

Alias records offer better performance, lower costs, and native integration with AWS health checks. For the Zone Apex (root domain), they are not just a preference; they are the only valid technical solution to bridge the gap between modern cloud infrastructure and legacy DNS protocols.