Skip to content

Phase 3 · CLOUD

Route 53 & TLS with ACM

Day 55 of 90 ~50 min 0/20 in phase Builds on Day 54

By the end of today

  • Create a Route 53 hosted zone and add A, CNAME and alias records
  • Request a free public TLS certificate from ACM with DNS validation
  • Explain alias records and why a CNAME can't sit at the zone apex

Route 53 and ACM: the address book and the wax seal for your domain

Section 1 of 5 · ~3 min

Every server you launched this phase has a raw IP or an ugly AWS name like ec2-54-81-152-7.compute-1.amazonaws.com. Nobody types that. Route 53 is AWS’s DNS service: it turns a human name like app.example.com into the address of whatever is serving it, fast enough (the “53” is the DNS port) to sit in front of production traffic.

The unit you work in is a hosted zone — a container for all the DNS records of one domain. Create a hosted zone for example.com and Route 53 hands you four name servers (NS records like ns-123.awsdns-45.com); you paste those at your domain registrar, and from then on Route 53 answers the world’s questions about your domain. Inside the zone you add records:

  • A — name → IPv4 address. AAAA — name → IPv6.
  • CNAME — an alias from one name to another name (www.example.comapp.example.com). A CNAME cannot live at the zone apex (example.com, no subdomain) — the DNS spec forbids it.
  • Alias — a Route 53-only record that points a name straight at an AWS resource: an ALB, CloudFront, or an S3 website. Unlike a CNAME it works at the apex, it is free to query, and it tracks the target’s changing IPs automatically. This is how you point example.com at yesterday’s load balancer.

That covers where traffic goes. The other half of a real domain is TLS — the padlock. ACM (AWS Certificate Manager) issues free public TLS certificates and renews them automatically, so you never hand-copy a .pem or wake to an expired cert. You request a cert for example.com, choose DNS validation, and ACM hands you a CNAME record to add to your hosted zone. Once ACM sees that record it knows you control the domain, issues the cert, and — because the record stays — renews it every year with no action from you. You then attach the cert to an ALB or CloudFront, which terminates TLS for you.

Two gotchas worth burning in: an ACM cert lives in one region and can only attach to resources in that region — with one exception, CloudFront requires the cert in us-east-1 no matter where your users are. And DNS validation only completes if your domain’s NS records actually point at Route 53.

A browser asks Route 53 for app.example.com; a Route 53 alias record points at an Application Load Balancer that terminates TLS with an ACM certificate and forwards the request to an EC2 instance behind it. Browser https://app.example.com Route 53 alias record ALB ACM cert · TLS EC2 your app
Route 53 resolves the name to an alias, the ALB terminates TLS with its ACM cert, and the request reaches your EC2 box.

Real world: Route 53 is the internet’s address book and ACM is the wax seal on the envelope. The address book turns “example.com” into directions to the right building even after the tenant moves — that’s exactly what an alias record does, always pointing at wherever the building is now. The wax seal proves the letter really came from you and wasn’t steamed open in transit — that’s the TLS certificate on every https:// request.

A named example makes it concrete: amazon.com itself is served by Route 53 — dig its NS records and they resolve to awsdns name servers — and every https:// request to it rides an ACM-managed certificate. The same two services you wire up by hand today run the retail front door.

Today you create a hosted zone, add records, request a free ACM certificate with DNS validation, see how it validates, and tear it all down.

Hands-On Lab

Section 2 of 5 · ~4 min

What this costs: about ₹45/month (~$0.50) only while the hosted zone exists — Route 53 charges $0.50 per hosted zone per month, NOT prorated — but AWS does not charge at all if you delete the zone within 12 hours of creating it, so this create-and-delete-in-one-sitting lab is effectively free. ACM public certificates are free, and so are DNS queries against alias records. This lab launches no ALB and no EC2 — those are not free (an ALB alone is roughly ₹1,500/month), so we teach the alias-to-ALB wiring in the concept and Go Deeper only, never leaving one running. You do need a domain you control to finish DNS validation; if you don’t own one, read this as the concept-only path — every command still shows you the exact shape of the records. Steps 8–10 delete the certificate, the records and the hosted zone, so nothing keeps billing.

Budget about 25 minutes. Drive this from the AWS CLI v2 as your day-47 IAM user (not root). Route 53 is a global service, so region doesn’t matter for the zone; ACM certs are regional, and we request ours in us-east-1. Swap example.com for a domain you actually control — zone IDs, name servers and ARNs below are examples, yours will differ.

# 1. Confirm you're your day-47 IAM user (NOT root).
aws sts get-caller-identity
# Output (your Account and Arn will differ):
# {
#     "UserId": "AIDA...EXAMPLE",
#     "Account": "123456789012",
#     "Arn": "arn:aws:iam::123456789012:user/admin-you"
# }
# 2. Create a hosted zone for your domain. The caller-reference must be unique per call.
ZONE=$(aws route53 create-hosted-zone \
  --name example.com \
  --caller-reference "m90-$(date +%s)" \
  --query 'HostedZone.Id' --output text)
echo "$ZONE"
# Output (yours will differ — the /hostedzone/ prefix is normal):
# /hostedzone/Z0123456789ABCDEFGHIJ
# 3. Read the 4 name servers Route 53 assigned — paste these at your domain registrar.
aws route53 get-hosted-zone --id "$ZONE" \
  --query 'DelegationSet.NameServers' --output text
# Output (yours will differ):
# ns-123.awsdns-45.org  ns-678.awsdns-90.co.uk  ns-234.awsdns-11.com  ns-567.awsdns-22.net
# 4. Add a simple A record: app.example.com -> an IPv4 address (stand-in for a real server).
aws route53 change-resource-record-sets --hosted-zone-id "$ZONE" \
  --change-batch '{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"app.example.com","Type":"A","TTL":300,"ResourceRecords":[{"Value":"203.0.113.10"}]}}]}'
# Output (the change is PENDING until it propagates):
# {
#     "ChangeInfo": { "Status": "PENDING", "Id": "/change/C0123456789ABC" }
# }
# 5. Request a FREE public TLS certificate for your domain, DNS validation.
CERT=$(aws acm request-certificate \
  --domain-name example.com \
  --subject-alternative-names www.example.com \
  --validation-method DNS --region us-east-1 \
  --query 'CertificateArn' --output text)
echo "$CERT"
# Output (yours will differ):
# arn:aws:acm:us-east-1:123456789012:certificate/abcd1234-ef56-7890-ab12-cd34ef567890
# 6. Read the CNAME record ACM wants you to publish to prove you own the domain.
#    (If this returns null, ACM hasn't populated the record yet — wait a few seconds and re-run.)
aws acm describe-certificate --certificate-arn "$CERT" --region us-east-1 \
  --query 'Certificate.DomainValidationOptions[0].ResourceRecord'
# Output (yours will differ — a random validation host and target):
# {
#     "Name": "_a1b2c3.example.com.",
#     "Type": "CNAME",
#     "Value": "_x9y8z7.acm-validations.aws."
# }
# 7. Publish that validation CNAME into your hosted zone so ACM can verify it.
aws route53 change-resource-record-sets --hosted-zone-id "$ZONE" \
  --change-batch '{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"_a1b2c3.example.com.","Type":"CNAME","TTL":300,"ResourceRecords":[{"Value":"_x9y8z7.acm-validations.aws."}]}}]}'
# Output:
# {
#     "ChangeInfo": { "Status": "PENDING", "Id": "/change/C0987654321XYZ" }
# }

Once your registrar delegates the domain to the Route 53 name servers from step 3, ACM validates within minutes — aws acm wait certificate-validated --certificate-arn "$CERT" --region us-east-1 blocks until the status is ISSUED. If the domain isn’t delegated, the cert stays PENDING_VALIDATION; that’s expected on a throwaway zone, so we tear down now regardless.

# 8. TEARDOWN starts. Delete the certificate (works because it's attached to nothing).
aws acm delete-certificate --certificate-arn "$CERT" --region us-east-1
echo "cert deleted"
# Output:
# cert deleted
# 9. Delete the records you added — a hosted zone won't delete while it holds custom records.
aws route53 change-resource-record-sets --hosted-zone-id "$ZONE" \
  --change-batch '{"Changes":[
    {"Action":"DELETE","ResourceRecordSet":{"Name":"app.example.com","Type":"A","TTL":300,"ResourceRecords":[{"Value":"203.0.113.10"}]}},
    {"Action":"DELETE","ResourceRecordSet":{"Name":"_a1b2c3.example.com.","Type":"CNAME","TTL":300,"ResourceRecords":[{"Value":"_x9y8z7.acm-validations.aws."}]}}
  ]}'
# Output:
# {
#     "ChangeInfo": { "Status": "PENDING", "Id": "/change/C0abc123def456" }
# }
# 10. Delete the hosted zone — the step that stops the $0.50/month charge.
aws route53 delete-hosted-zone --id "$ZONE" \
  --query 'ChangeInfo.Status' --output text
# Output:
# PENDING

Read it back: a hosted zone held your records, an alias would have pointed the apex at an ALB, and ACM proved domain ownership through a single CNAME — then step 10 deleted the zone so the $0.50/month meter stops. Create, validate, delete: the whole life of a domain’s DNS and TLS in one sitting.

Common Errors & Fixes

Section 3 of 5 · ~2 min

These three catch almost everyone wiring up their first domain. Read the error text slowly — parsing it is the actual skill.

Common error: Trying to point the bare domain (example.com, no subdomain) at a load balancer with a CNAME:

An error occurred (InvalidChangeBatch) when calling the ChangeResourceRecordSets operation: [RRSet of type CNAME with DNS name example.com. is not permitted at apex in zone example.com.]

Why: The DNS spec forbids a CNAME coexisting with the zone-apex records (SOA and NS) that every zone must carry, so Route 53 rejects a CNAME at the apex outright.

Fix: Use a Route 53 alias record instead — an A record with an AliasTarget pointing at the ALB, CloudFront or S3. Alias records are the AWS-only trick that legally sits at the apex and, as a bonus, cost nothing to query.

How you’d spot it in prod: is not permitted at apex always means someone reached for a CNAME on the naked domain — swap it for an alias A (and AAAA) record and the change applies.

Common error: Deleting a hosted zone that still contains records you added:

An error occurred (HostedZoneNotEmpty) when calling the DeleteHostedZone operation: The specified hosted zone contains non-required resource record sets and so cannot be deleted.

Why: Route 53 deletes the default SOA and NS records for you, but not any A, CNAME or alias records you created — it refuses rather than silently drop DNS entries that might still be serving live traffic.

Fix: Delete every custom record first with a DELETE change batch (step 9), leaving only the default SOA and NS, then re-run delete-hosted-zone. That’s exactly why the teardown deletes records before the zone.

How you’d spot it in prod: A Terraform destroy or cleanup script failing with HostedZoneNotEmpty means a record outlived its owner — remove the leftover record sets, then the zone drops.

Common error: Waiting on a certificate that never leaves PENDING_VALIDATION:

Waiter CertificateValidated failed: Max attempts exceeded

Why: ACM only issues the cert once it can resolve the validation CNAME it gave you. If the domain’s NS records don’t actually point at the Route 53 hosted zone, or the validation CNAME was never published, ACM sees nothing and the cert sits pending forever.

Fix: Confirm the validation CNAME exists in the zone (step 7) and that your registrar delegates the domain to the four Route 53 name servers from step 3. Check propagation with dig +short _a1b2c3.example.com CNAME; once it resolves, ACM validates within minutes.

How you’d spot it in prod: A cert stuck pending on deploy is nearly always a delegation gap — the domain isn’t really on Route 53 yet — not an ACM fault. Verify the NS chain with dig NS example.com before blaming the certificate.

Route 53 and ACM Interview Questions

Section 4 of 5 · ~1 min

Cover the answers below and say your own version out loud first — define a hosted zone, an alias record, and how ACM DNS validation works before you reveal each answer. Recalling before revealing is what makes these stick when an interviewer asks them cold. The four questions and answers render right after this note.

Go Deeper

Section 5 of 5 · ~1 min

Optional extras if you have ~30 more minutes today:

  • 5 min — Read the Route 53 choosing between alias and CNAME doc and note the exact case an alias handles that a CNAME can’t: the zone apex.
  • 10 min — If the ALB from day 54 is still up (it is not free — bring it up only briefly and delete it the moment you’re done), create an alias A record at your apex pointing at it, attach your ACM cert to the ALB’s HTTPS listener, and curl -v https://example.com to see the certificate served.
  • 10 min — Read ACM’s DNS validation and managed renewal page to understand why leaving the validation CNAME in place is what makes auto-renewal work.
  • 5 min — Skim Route 53 routing policies — simple, weighted, latency, failover, geolocation — so you know which one a multi-region setup reaches for.
What is a Route 53 alias record and how does it differ from a CNAME? Both

Both point one name at another, but an alias record is Route 53-specific and a CNAME is standard DNS. The practical difference: a CNAME cannot sit at the zone apex — the bare `example.com` — because DNS won't let a CNAME coexist with the mandatory SOA and NS records there. An alias record can, so it's how you point the naked domain at an ALB, CloudFront or S3. Alias records also resolve to the target's current IPs automatically, cost nothing to query, and Route 53 answers them internally. A CNAME works only on subdomains like `www`, points at any hostname anywhere, and is billed per query. Rule of thumb: alias for AWS targets and the apex, CNAME for external subdomains.

How does ACM DNS validation work, and why prefer it over email validation? Product

When you request an ACM certificate with DNS validation, ACM gives you a CNAME record to publish in your domain's DNS. Once ACM can resolve that record, it knows you control the domain and issues the cert. The reason it beats email validation is renewal: as long as that CNAME stays in place, ACM revalidates and renews the certificate automatically every year with zero human action — no expired-cert outages. Email validation, by contrast, sends an approval link to the domain's registered contacts and needs someone to click it, both at issue time and on renewal, which is fragile and easy to miss. For anything automated or long-lived, DNS validation into a Route 53 hosted zone is the set-and-forget choice.

Why must an ACM certificate for CloudFront live in us-east-1? Both

ACM certificates are regional resources — a cert issued in `ap-south-1` can only be attached to load balancers and other resources in `ap-south-1`. So for an ALB you request the cert in the same region as the ALB. CloudFront is the exception everyone trips on: it's a global edge service, but it only reads certificates from `us-east-1`, so a cert for a CloudFront distribution must be requested there regardless of where your users or origin live. If you attach the wrong region's cert, the console simply won't list it. The habit: ALB cert in the ALB's region, CloudFront cert always in `us-east-1`.

What are the main Route 53 record types and routing policies, and when do you use each? Service

The everyday records are A (name to IPv4), AAAA (to IPv6), CNAME (one name to another, subdomains only), MX (mail servers), TXT (SPF, DKIM and domain-verification strings), NS (delegation), and Route 53's own alias records for AWS targets. On top of record types, Route 53 has routing policies: simple for one target, weighted for splitting traffic by percentage (handy for canary releases), latency-based to send users to the closest region, failover paired with health checks for active-passive DR, and geolocation to route by country. Most zones start with plain A or alias and simple routing; you reach for weighted or latency policies once you run in more than one region.

Mark Day 55 complete

Tomorrow you play: Database Recovery

Stuck on today’s lab? Ask in Mission 90 Q&A