Course outline

8.2

CNAME vs Alias

Why the zone apex cannot be a CNAME, what Alias does instead, and its valid targets.

16 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain why AWS resources such as load balancers give you a hostname instead of fixed IP addresses, and what that means for your DNS records.
  • Explain, from the DNS standard, why the zone apex (example.com) can never be a CNAME.
  • Describe what an Alias record is, how Route 53 answers it, and how it differs from a CNAME in type, TTL, cost and health.
  • List the AWS resources an Alias can point to, the conditions each one needs, and the targets it cannot point to (EC2 DNS names, RDS endpoints).
  • Choose the right record for any name and target: Alias, A with an Elastic IP, or CNAME, and answer the guaranteed exam question in seconds.

#Why this question is guaranteed in the exam

The owner’s notes put it bluntly: one question on CNAME vs Alias is practically guaranteed. It shows up on its own and, even more often, hidden inside a question about load balancers or CloudFront. The idea behind it is short, so learn it properly once.

#AWS gives you a name, not an address

When you create an Application Load Balancer (lesson 6.3), AWS does not hand you an IP address. It gives you a DNS name such as:

my-alb-1234.us-east-1.elb.amazonaws.com

CloudFront gives you d111111abcdef8.cloudfront.net, API Gateway gives you …execute-api.us-east-1.amazonaws.com, an S3 website gives you …s3-website-us-east-1.amazonaws.com. The reason is the same every time: the IP addresses behind these services belong to AWS and change. A load balancer adds nodes when traffic grows, removes them when it falls, and replaces nodes that fail. Each new node has a new address. AWS keeps the name pointing at whatever addresses are current, with a short TTL (60 seconds for a load balancer), and promises nothing about the addresses themselves.

Your users, though, want to type your name: example.com or app.example.com. So in your hosted zone you need a record that says “this name of mine means that AWS name”. DNS has a standard record for that, the CNAME, and Route 53 adds its own, the Alias. Which one works depends on where the name sits.

#CNAME: a pointer to another name

A CNAME (canonical name) record maps one hostname to another hostname, not to an address. The DNS lesson covers it in general; here is what matters on AWS.

  • When a resolver asks for www.example.com and finds a CNAME, the answer is “this name is really my-alb-1234…elb.amazonaws.com”. The resolver then has to look up that second name to get the IPs. On a cold cache that is an extra round trip.
  • The target can be any hostname on the internet: an AWS name, blog.example.net at a blogging company, a SaaS shop. Route 53 does not have to host the target.
  • A CNAME redirects every query type for the name (A, AAAA, MX, TXT…), because it says the whole name lives elsewhere.
  • You choose its TTL, and Route 53 charges for CNAME queries (about $0.40 per million in a public hosted zone). If the CNAME points to another record that is also in Route 53, each lookup is billed as two queries: the CNAME, then the record it points to.

#Why the zone apex cannot be a CNAME

The zone apex (also called the root domain or naked domain) is the name of the hosted zone itself: example.com in the example.com zone. Two rules collide there:

  1. A CNAME must stand alone. The DNS standard (RFC 1034, section 3.6.2) says that if a name has a CNAME record, it may have no other records. That follows from what a CNAME means: “everything about this name is somewhere else”. A resolver that finds a CNAME follows it for every question, so any other record at the same name would be unreachable and contradictory.
  2. The apex is never empty. Every zone has an SOA record (the zone’s settings) and NS records (its name servers) at the apex. Route 53 creates both the moment you create the hosted zone, and you cannot delete them. Most zones also have MX (mail) and TXT (verification, SPF) records there.

So a CNAME at the apex would have to share the name with SOA and NS, which the standard forbids. If a DNS server allowed it anyway, a question for the MX or NS records of example.com would be redirected to the load balancer’s name, and mail and delegation would break. Route 53 simply refuses: you cannot create a CNAME whose name is the same as the hosted zone. The same “stands alone” rule is why a www CNAME cannot also have a TXT record next to it.

What the zone apex accepts

Try to add records to example.com and watch Route 53 accept or reject them. The table shows the records that already exist at that name.

Scenario

Youconsole or CLI
Route 53change API
Hosted zoneexample.com
CNAME example.com → ALB

Records at example.com

NameTypeValue
example.comNSns-1.awsdns-01.org …
example.comSOAns-1.awsdns-01.org …
example.comMX10 mail.example.com
Step 1 of 3
1

Every hosted zone is born with an NS record and an SOA record at its apex; here an MX record for mail sits there too. You ask for a CNAME at example.com pointing to the ALB.

#Alias: Route 53 answers for the target

An Alias record is a Route 53-specific extension to DNS. You create a record of a normal type, almost always A (IPv4) or AAAA (IPv6), switch on “Alias”, and choose an AWS resource as the target instead of typing an IP address.

When a query arrives, Route 53 itself looks up the target’s current addresses inside AWS and answers with plain A or AAAA records. The resolver never learns that an Alias exists:

  • No extra lookup. The client receives IP addresses in the first answer, not another name to resolve. dig shows only A lines; the Alias flag is visible only in the Route 53 console or API (list-resource-record-sets).
  • It works at the apex. To the outside world it is an A record, so it can sit next to SOA, NS, MX and TXT. This is the main reason it exists.
  • It follows the target automatically. When the load balancer’s IPs change, Route 53 starts answering with the new ones. Nobody edits a record.
  • You cannot set its TTL. For an AWS resource, Route 53 uses the resource’s own TTL (60 seconds for a load balancer). For an Alias to another record, it uses that record’s TTL.
  • Queries are free when the target is an AWS resource (load balancer, CloudFront, API Gateway, S3 website, and the rest of the list below). A CNAME to the same load balancer is charged.
  • Evaluate Target Health. An Alias can inherit the health of its target. With failover, weighted, latency and other non-simple policies, Route 53 stops returning a target that is unhealthy, without a separate Route 53 health check.
  • Name and type must match. Route 53 answers an Alias only when the query’s name and type match. An A Alias does not answer AAAA questions, so for IPv6 you create a second Alias of type AAAA.

CNAMEAlias

  • Standard DNS, every DNS provider has it.
  • Maps a name to any other hostname, AWS or not.
  • Not allowed at the zone apex; cannot share its name with any other record.
  • Resolver must make a second lookup for the target name.
  • You set the TTL.
  • Route 53 charges for queries.
  • No health awareness of its own.
  • Route 53-only extension.
  • Maps a name to selected AWS resources or another record in the same hosted zone.
  • Works at the apex and on subdomains; coexists with other records.
  • Route 53 answers with the IP addresses directly (type A/AAAA).
  • TTL comes from the target; you cannot set it.
  • Free for AWS resource targets.
  • Evaluate Target Health built in.

CNAME lookup vs Alias answer

Follow one query through the resolver. With a CNAME, Route 53 hands back another name and the resolver must look that up too; with an Alias, Route 53 looks up the target itself and answers with IP addresses.

Scenario

www.example.com is a CNAME to the ALB’s DNS name.

Browser
Resolverrecursive
Route 53example.com zone
Target’s DNSthe other name
www.example.com A?
Step 1 of 6
1

The browser needs an IP address for www.example.com and asks its resolver. The full chain (root, TLD, authoritative) is in the DNS lesson; here we start where Route 53 is asked.

Self-checkQuestion

The hosted zone example.com already has NS, SOA and MX records at the apex. Which of these can you add at the name example.com?

#Alias follows the load balancer

This is the property that makes Alias the default for AWS resources. Watch the load balancer replace a node: the Alias picks up the new address within one TTL, while a hand-made A record keeps pointing at an address that is gone. The last scenario shows Evaluate Target Health sending users to a backup when every target behind the load balancer fails.

When the load balancer’s IPs change

AWS replaces and scales load balancer nodes, and their IP addresses change. Compare an Alias, which follows the change, with an A record someone hard-coded to an old IP. The last scenario shows Evaluate Target Health.

Scenario

us-east-1
AZ a
AZ b
Users
Route 53example.com
ALBone DNS name
S3 websitesorry page
ALB node198.51.100.10
ALB node198.51.100.11
Web 1
Web 2
example.com A?.10, .11 · TTL 60
Step 1 of 5
1

example.com is an Alias to the ALB. Users ask Route 53 and receive the two node addresses, cached for the ALB’s 60-second TTL.

#What an Alias can point to

The notes list six targets; the slides add two more; the current Route 53 documentation lists these:

Alias targetRecord typeWhat must be true
Elastic Load Balancing: ALB, NLB, CLBA, and AAAA for a dual-stack load balancerNothing special; from another account, type its DNS name (the console adds dualstack.)
CloudFront distributionA, and AAAA if IPv6 is onThe distribution lists the record name as an alternate domain name; public hosted zone only; Evaluate Target Health not available
API Gateway (regional or edge-optimised API)AA custom domain name with the record’s name exists in API Gateway
Elastic Beanstalk environmentAThe environment’s domain includes the Region (all environments since early 2016); older ones need a CNAME
S3 bucket configured as a static websiteABucket name equals the record name (example.com needs a bucket called example.com) and website hosting is on
VPC interface endpointAUsually in a private hosted zone, to give an endpoint a friendly name
Global Accelerator acceleratorA (AAAA for dual-stack)Works across accounts by DNS name
Another record in the same hosted zoneSame type as the target record (any type except NS and SOA)Same hosted zone only; at the apex the target cannot be a CNAME
App Runner service, AppSync domain name, OpenSearch Service custom domainA (OpenSearch also AAAA)The record name matches the service’s custom domain

The last row and the VPC interface endpoints are not in the notes; App Runner, AppSync and OpenSearch are not on the slides either. They are real Alias targets today but rarely asked in the exam. CloudFront, Global Accelerator, API Gateway, S3 websites and VPC endpoints each get their own chapter later; for now it is enough to know that each one gives you an AWS hostname, which is exactly the situation Alias was built for.

#What an Alias cannot point to

  • An EC2 instance or its DNS name (ec2-203-0-113-25.compute-1.amazonaws.com). There is no Alias for EC2. For one instance, attach an Elastic IP (lesson 3.6) and create a normal A record with it; for several instances, put a load balancer in front and Alias to the load balancer.
  • An RDS endpoint (mydb.abc123.us-east-1.rds.amazonaws.com). Use a CNAME on a subdomain such as db.example.com, usually in a private hosted zone. On failover RDS points the endpoint name at the new primary (lesson 7.1), so the CNAME keeps working.
  • Anything outside AWS, and records in a different hosted zone. Those need a CNAME (on a subdomain).

#Choosing the record: the decision rule

  1. Is the target an IP address you control?

    One EC2 instance with an Elastic IP, an NLB’s static IPs for an allowlist, an on-premises server: create an A (or AAAA) record with that address. You set the TTL; queries are charged.

  2. Is the target an AWS resource on the Alias list?

    Load balancer, CloudFront, API Gateway, Beanstalk, S3 website, VPC interface endpoint, Global Accelerator, App Runner, AppSync, OpenSearch: create an Alias A record (plus Alias AAAA for IPv6). This works at the apex and on subdomains, is free, and follows IP changes. Even on a subdomain where a CNAME would work, the Alias is the better choice.

  3. Is the target another record in the same hosted zone?

    Create an Alias of the same type as that record, for example example.com Alias → www.example.com when www is itself an A or Alias A record.

  4. Otherwise, it is a hostname you cannot Alias

    RDS endpoint, a non-regional old Beanstalk name, a SaaS or another provider’s hostname, a record in another zone: create a CNAME, and only on a subdomain. If it must be the apex, put CloudFront in front (Alias to CloudFront), use static IPs the provider guarantees (A record), or redirect example.com to www.example.com and CNAME www.

Try every combination yourself:

Which record should I create?

Pick the name you are creating and what it should point to. The card shows the record Route 53 needs, why, its TTL, its query cost and what must be true first.

Record name

Points to

Create

Alias record, type A (plus AAAA for IPv6)

At the apex only an Alias can point to an AWS hostname: a CNAME is not allowed next to the NS and SOA records. Route 53 looks up the target itself and answers with its current IPs.

NameTypeValue
example.comA (Alias)my-alb-1234.us-east-1.elb.amazonaws.com
TTL
Not settable: Route 53 uses the target’s own TTL (60 s for a load balancer).
Query cost
Free: Route 53 does not charge for Alias queries to AWS resources.
Check first
Add a second Alias of type AAAA if the load balancer is dual-stack. Turn on Evaluate Target Health when the record has an alternative (failover, weighted, latency).

#What goes wrong

SymptomCauseFix
The console or API rejects a CNAME for example.comCNAME at the zone apexAlias A (and AAAA) to the AWS resource
A TXT or MX record cannot be added to www.example.comwww is a CNAME, which must stand aloneTurn www into an Alias A record, then add the TXT
Part of the users get timeouts weeks after go-liveAn A record holds the load balancer’s old IPsAlias to the load balancer
The S3 bucket does not appear in the Alias target listBucket name differs from the record name, or website hosting is offBucket named exactly like the record, static website hosting on (or CloudFront in front)
The CloudFront distribution does not appear, or returns 403 for your nameThe record name is not an alternate domain name of the distribution, or the zone is privateAdd the alternate domain name; use a public hosted zone
IPv6 users only ever reach you over IPv4Only an A Alias existsAdd an AAAA Alias to the same dual-stack target
The apex Alias to www.example.com is rejectedwww is a CNAME, so the Alias would be an apex CNAMEAlias the apex directly to the resource, or make www an Alias A
Failover never happens although the ALB’s targets are all downEvaluate Target Health is off, or the record uses simple routingUse a failover (or other) policy with Evaluate Target Health on
The DNS bill is higher than expectedCNAMEs to load balancers or chained CNAMEs, billed per query (twice for a Route 53 target)Replace with Alias records

#In system design

  • Apex plus www. A typical public site has example.com as an Alias A/AAAA to CloudFront (or an ALB) and www.example.com either as another Alias to the same target or as an Alias to the apex record. Both are free and follow the target.
  • Exam questions mix chapters. The notes’ closing advice: Route 53 questions are often combined with load balancers and CloudFront. Whenever the answer options include a load balancer or a distribution and a domain, check the record type first: Alias for the apex, never a CNAME there, never copied IPs.
  • Static IPs and Alias are not opposites. When a partner must allowlist fixed addresses, use an NLB with Elastic IPs or Global Accelerator for the addresses, and still point your domain at it with an Alias.
  • Multi-account setups. A load balancer or distribution in another account does not appear in the console’s Alias list, but you can type its DNS name (and Route 53 still answers for it). An Alias cannot reach a record in another hosted zone; use a CNAME for that.
  • Databases stay on CNAMEs. Give applications a stable name such as db.internal.example.com as a CNAME to the RDS endpoint in a private hosted zone; swapping the database later means changing one CNAME, not every application’s configuration.

#Try it yourself

Find the load balancer’s DNS name and its own hosted zone ID (an Alias needs both):

aws elbv2 describe-load-balancers --names my-alb \
  --query 'LoadBalancers[0].[DNSName,CanonicalHostedZoneId]'

Create (or update) an Alias A record at the apex. The HostedZoneId inside AliasTarget is the load balancer’s zone ID from the command above, not your own zone’s ID. Notice there is no TTL field:

cat > alias.json <<'EOF'
{
  "Comment": "apex Alias to the ALB",
  "Changes": [{
    "Action": "UPSERT",
    "ResourceRecordSet": {
      "Name": "example.com",
      "Type": "A",
      "AliasTarget": {
        "HostedZoneId": "Z35SXDOTRQ7X7K",
        "DNSName": "dualstack.my-alb-1234.us-east-1.elb.amazonaws.com",
        "EvaluateTargetHealth": true
      }
    }
  }]
}
EOF
aws route53 change-resource-record-sets --hosted-zone-id Z0123456789EXAMPLE --change-batch file://alias.json

Now try the forbidden one, a CNAME at the apex. Route 53 rejects the whole change batch with an InvalidChangeBatch error:

aws route53 change-resource-record-sets --hosted-zone-id Z0123456789EXAMPLE --change-batch '{
  "Changes": [{ "Action": "CREATE", "ResourceRecordSet": {
    "Name": "example.com", "Type": "CNAME", "TTL": 300,
    "ResourceRecords": [{ "Value": "my-alb-1234.us-east-1.elb.amazonaws.com" }] } }] }'

Compare what resolvers see for an Alias and for a CNAME:

dig +noall +answer example.com A        # only A lines, TTL counting down from 60
dig +noall +answer www.example.com A    # a CNAME line, then the ALB's A lines
nslookup -type=AAAA example.com         # empty unless you also created an AAAA Alias

See the Alias flag that dig never shows, and ask Route 53 directly what it would answer:

aws route53 list-resource-record-sets --hosted-zone-id Z0123456789EXAMPLE \
  --query "ResourceRecordSets[?Name=='example.com.']"
aws route53 test-dns-answer --hosted-zone-id Z0123456789EXAMPLE \
  --record-name example.com --record-type A

The fixed hosted zone IDs you will meet most: CloudFront is always Z2FDTNDATAQYW2, Global Accelerator Z2BJ6XQ5FK7U4H; load balancers, S3 websites and Beanstalk have one ID per Region (the ALB example above is the us-east-1 value).

#Summary

Key takeaways

  • AWS resources (load balancers, CloudFront, API Gateway, S3 websites…) give you a DNS name because their IP addresses change. Never copy those IPs into an A record.
  • CNAME: name → any other hostname, AWS or not; extra lookup; you set the TTL; charged; must stand alone, so it is never allowed at the zone apex, which always holds SOA and NS.
  • Alias: Route 53-only; type A/AAAA (or the same type as a target record in the same zone); Route 53 resolves the target itself and answers with IPs; works at the apex; no TTL to set (uses the target’s, 60 s for a load balancer); free for AWS resources; Evaluate Target Health; answers only matching types, so add AAAA for IPv6.
  • Alias targets: ELB (ALB/NLB/CLB), CloudFront, API Gateway, Elastic Beanstalk, S3 website (bucket name = record name), VPC interface endpoints, Global Accelerator, another record in the same hosted zone, plus App Runner, AppSync and OpenSearch Service.
  • Not Alias targets: EC2 DNS names (use an A record with an Elastic IP), RDS endpoints (use a CNAME on a subdomain), anything outside AWS or in another zone (CNAME on a subdomain).
  • Exam reflex: root domain → ALB / CloudFront / S3 website → Alias. Always.