Route 53: DNS for your apps
Create a private hosted zone in the console, add A, CNAME and alias records, pick a routing policy, add health checks, and clean up without buying a domain.
By the end of this lesson you'll be able to
0 of 5 completeDNS in one minute
DNS turns a name like api.example.com into an address a computer can connect to. Route 53 is AWS's DNS
service: it hosts your DNS records, answers queries from anywhere in the world, health-checks endpoints and can
register domains. The name comes from DNS's port, 53.
Everything below was done in a real practice account with a private zone, which costs nothing if deleted within 12 hours, and then deleted. No domain was bought and no public DNS changed.
Hosted zones
A hosted zone holds the records for one domain:
| Zone | Answers | Use for |
|---|---|---|
| Public | anyone on the internet | your website and APIs (example.com) |
| Private | only from VPCs you associate with it | internal service names (db.academy.internal) |
Route 53 → Hosted zones → Create hosted zone:
A private zone needs the VPC's DNS hostnames and DNS resolution settings turned on; the default VPC and lesson 4's wizard VPC have both. A new zone starts with two records Route 53 manages for you: NS (the name servers answering for the zone) and SOA (zone metadata).
Records
| Type | Points to | Example |
|---|---|---|
| A / AAAA | an IPv4 / IPv6 address | api.academy.internal → 10.0.0.10 |
| CNAME | another name (never at the zone apex) | www → web.academy.internal |
| Alias | an AWS resource: ALB, CloudFront, S3 website, another record | example.com → my-alb-123.elb.amazonaws.com |
| MX / TXT | mail servers / text, such as domain verification | TXT "v=spf1 …" |
Alias is Route 53's own record: it works at the zone apex (example.com itself, where CNAMEs aren't
allowed), follows the target's IP addresses as they change, and queries to AWS targets are free. Point domains at
lesson 5's load balancer or lesson 9's CloudFront with an alias.
TTL (time to live) is how long resolvers cache an answer. 300 seconds is a sensible default; lower it a day before a planned change so the switch spreads quickly.
Routing policies
The record wizard shows every policy:
| Policy | Answers with | Use for |
|---|---|---|
| Simple | the same value for everyone | one endpoint |
| Weighted | each record in proportion to its weight | canary releases: 90% old, 10% new |
| Latency | the Region with the lowest latency to the user | apps running in several Regions |
| Failover | primary while healthy, otherwise secondary | disaster recovery |
| Geolocation | by the user's country or continent | legal or language requirements |
| Multivalue | up to eight healthy records at random | simple client-side spreading |
Health checks
Attach a health check to a failover or weighted record, and Route 53 stops returning an unhealthy answer. Check a
path that proves the app works (/health that touches the database), not just that a port is open. Health checks
cost a little per month each, so this lesson only opened the form.
Domain registration
Registered domains → Register domains buys a domain through Route 53 and creates its public hosted zone for you. If your domain is registered elsewhere, create a public hosted zone and set the registrar's name servers to the four in its NS record. Registration costs real money and renews yearly, so it's never part of a practice mission.
Private DNS for a VPC
Create a private hosted zone attached to your default VPC, add two A records and a CNAME, list them, then delete the records and the zone and confirm it's gone.
Five records (NS, SOA, two A, one CNAME), then no academy.internal zoneReveal one safe solution
$ VPC=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true --query 'Vpcs[0].VpcId' --output text) $ Z=$(aws route53 create-hosted-zone --name academy.internal --caller-reference academy-$RANDOM \ --vpc VPCRegion=ap-south-1,VPCId=$VPC --query HostedZone.Id --output text) $ cat > rec.json <<'EOF' {"Changes":[ {"Action":"CREATE","ResourceRecordSet":{"Name":"api.academy.internal","Type":"A","TTL":300,"ResourceRecords":[{"Value":"10.0.0.10"}]}}, {"Action":"CREATE","ResourceRecordSet":{"Name":"web.academy.internal","Type":"A","TTL":300,"ResourceRecords":[{"Value":"10.0.0.20"}]}}, {"Action":"CREATE","ResourceRecordSet":{"Name":"www.academy.internal","Type":"CNAME","TTL":300,"ResourceRecords":[{"Value":"web.academy.internal"}]}}]} EOF $ aws route53 change-resource-record-sets --hosted-zone-id $Z --change-batch file://rec.json $ aws route53 list-resource-record-sets --hosted-zone-id $Z --query 'ResourceRecordSets[].[Name,Type,ResourceRecords[0].Value]' --output text academy.internal. NS ns-1536.awsdns-00.co.uk. academy.internal. SOA ns-1536.awsdns-00.co.uk. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400 api.academy.internal. A 10.0.0.10 web.academy.internal. A 10.0.0.20 www.academy.internal. CNAME web.academy.internal $ sed 's/"CREATE"/"DELETE"/g' rec.json > del.json $ aws route53 change-resource-record-sets --hosted-zone-id $Z --change-batch file://del.json $ aws route53 delete-hosted-zone --id $Z $ aws route53 list-hosted-zones-by-name --dns-name academy.internal --query 'HostedZones[?Name==`academy.internal.`]' []
cat > rec.json <<'EOF'catprint a file>write output to a file, replacing it
aws route53 change-resource-record-sets --hosted-zone-id $Z --change-batch file://rec.jsonawsthe AWS command line
aws route53 list-resource-record-sets --hosted-zone-id $Z --query 'ResourceRecordSets[].[Name,Type,ResourceRecords[0].Value]' --output text--querypick fields from the JSON response--outputoutput format
Your name servers will differ. A delete batch must match each record exactly, which is why reusing the create
file with DELETE is the safe way to remove them.
Try it yourself
0 of 4 steps doneRun each task in your own account or terminal, then tick it off.
Quick check
Which hosted zone resolves names only inside associated VPCs?
Official reading for this lesson
Or get every quiz answer right and it completes itself.