Route 53 — Cheat Sheet (DVA-C02)
Verified against AWS documentation on 2026-10-12 · ⚠️ = changed vs older material: learn the value shown here (older practice material may say otherwise; full list in notes/route53-guide.md#changed-vs-older-material) · ⚠️ unverified = not confirmed in AWS docs, don't rely on it · explanations and examples: notes/route53-guide.md.
Hosted zones and record types
| Topic | Current facts | Memory hook |
|---|---|---|
| Domain at another registrar | Registrar, DNS and health checks are independent roles: use Route 53 DNS by setting the registrar's name servers to the hosted zone's 4 NS values | Point the registrar at the zone |
| Public vs private zone | Public answers the internet; private answers only associated VPCs; same name in both = split-view DNS; no conversion between them | |
| Private zone prerequisites | VPC attributes enableDnsHostnames and enableDnsSupport = true; CreateHostedZone callers also need ec2:DescribeVpcs |
|
| Missing record in a private zone | VPC Resolver returns NXDOMAIN; no fallback to the public zone |
Private zone wins, even empty-handed |
| Default records | NS (4 name servers) + SOA created with every public zone; don't delete them | |
| Record types | 17 ⚠️: A, AAAA, CAA, CNAME, DS, HTTPS, MX, NAPTR, NS, PTR, SOA, SPF, SRV, SSHFP, SVCB, TLSA, TXT (HTTPS, SSHFP, SVCB, TLSA since 2024-10-30; SSHFP and TLSA public zones only) | |
| SPF policies | Publish in a TXT record; the SPF type is no longer recommended |
|
| CNAME rules | Never at the zone apex; a name with a CNAME holds no other record |
A CNAME owns its name alone |
| Negative caching | NXDOMAIN/NODATA cached for the lower of SOA minimum TTL (86,400 s) and SOA TTL (900 s) |
Missing names are cached too |
| Change API | ChangeResourceRecordSets: batch of CREATE / DELETE / UPSERT, atomic; a DELETE must repeat every value; PENDING → INSYNC; aws route53 wait resource-record-sets-changed |
One batch, all or nothing |
| IAM conditions | route53:ChangeResourceRecordSetsNormalizedRecordNames (lowercase, no trailing dot), ...RecordTypes, ...Actions (uppercase values) with ForAllValues:StringEquals; no tag-based keys |
Name, type, action |
| API errors | InvalidChangeBatch 400 (batch fails validation) · PriorRequestNotComplete 400 (zone still busy: retry with growing waits) · Throttling / Rate exceeded 400 · NoSuchHostedZone 404 · HostedZoneNotEmpty 400 on zone delete (records left or DNSSEC on) |
|
| Global service | CloudTrail events under us-east-1; public query logs to a CloudWatch Logs group in us-east-1 |
Alias records, CNAME and TTL
| Feature | Alias | CNAME | Memory hook |
|---|---|---|---|
| Zone apex | Yes | No | Apex needs alias |
| Targets | Selected AWS resources or a record in the same zone | Any DNS name | |
| Query charge | Free for AWS resources | Billed; 2 queries when it points at another Route 53 name | Alias is free |
| TTL | Not settable; inherits the target's (ELB 60 s) | You set it | |
| Query types answered | Only its own type | Every type for the name | |
Seen in dig as |
Plain A/AAAA |
CNAME |
| Alias target | Record type | Hosted zone ID or rule |
|---|---|---|
| ALB / NLB / CLB | A or AAAA |
CanonicalHostedZoneId from describe-load-balancers (us-east-1 ALB Z35SXDOTRQ7X7K) |
| CloudFront distribution | A, plus AAAA with IPv6 |
Always Z2FDTNDATAQYW2; record name must be an alternate domain name; not in private zones; no EvaluateTargetHealth |
| API Gateway custom domain | A |
regionalHostedZoneId or distributionHostedZoneId from get-domain-names; record name = the custom domain name |
| S3 website endpoint | A |
Region's published ID; record name = bucket name; HTTP only |
| Elastic Beanstalk environment | A |
Region's ID; the domain must include the Region (older environments need a CNAME) |
| VPC interface endpoint | A |
The endpoint's HostedZoneId from describe-vpc-endpoints |
| Another record in the zone | That record's type (not NS/SOA) |
Same hosted zone only; apex alias can't target a CNAME |
| Added targets ⚠️ | App Runner, OpenSearch custom domains, AppSync domains, VPC Lattice custom domains, CloudFront distribution tenants | |
| Not alias targets | EC2 instance DNS names, RDS endpoints, names outside AWS | Use an Elastic IP A record or a CNAME |
| TTL topic | Current facts | Memory hook |
|---|---|---|
| Trade-off | TTL trades freshness for query volume: high = cheaper, edits show up late; low = edits and failovers show up fast, more billed queries | |
| Before a planned change | Lower the TTL (60–300 s) at least one old-TTL period ahead; raise it afterwards | Lower it yesterday |
| Records with health checks | TTL 60 s or less | |
| NS record | Typically 172,800 s (2 days); 60–900 s while migrating DNS to Route 53 |
Routing policies
| Policy | Answers with | Health checks | Private zone | Memory hook |
|---|---|---|---|---|
| Simple | All values of the one record, random order; never health-checked | No | Yes | Just answer |
| Weighted | One record with probability weight ÷ sum (0–255) | Yes | Yes | Shares, not percentages |
| Latency | Record of the Region with the lowest measured latency for the user | Yes | Yes | Fastest, not nearest |
| Failover | Primary while healthy, else secondary | Yes | Yes | Active-passive |
| Geolocation | Record of the user's US state, country or continent (smallest matching area wins), else * default |
Yes | Yes | Default or no answer |
| Geoproximity ⚠️ | Nearest resource after bias −99 to 99; plain record policy since 2024-01-10 (no Traffic Flow needed) | Yes | Yes | Distance with a bias |
| IP-based | Record mapped to the query's CIDR block (collection → location → blocks), else * |
Yes | No | Your own IP map |
| Multivalue answer | Up to 8 healthy values, a random set per resolver; can't be an alias; balances nothing | Yes | Yes | Eight healthy answers |
| Topic | Current facts | Memory hook |
|---|---|---|
| Private zone support ⚠️ | All policies except IP-based (latency and geolocation since 2022-03-16, geoproximity since 2024-01-10) | IP-based stays public |
| User location | EDNS0 client subnet if the resolver sends it, else the resolver's IP; not used in private zones | |
| Testing answers | aws route53 test-dns-answer with --resolver-ip, --edns0-client-subnet-ip, --edns0-client-subnet-mask (public zones only) |
Health checks and failover
| Topic | Current facts | Memory hook |
|---|---|---|
| Types | Endpoint (HTTP, HTTPS, TCP, string match), calculated, CloudWatch alarm; API also RECOVERY_CONTROL |
|
| Healthy rule | More than 18 % of checkers report healthy | 18 % says healthy |
| Check timing | HTTP/HTTPS: TCP connect within 4 s, then 2xx/3xx within 2 s; TCP: connect within 10 s | 4 + 2, or 10 |
| String matching | Body within 2 more seconds; string ≤ 255 characters, case-sensitive, in the first 5,120 bytes | |
| HTTPS checks | Certificates not validated; TLS 1.0–1.2; EnableSNI for servers that need the host name (without it: typically SSL alert handshake_failure) |
|
| Endpoint by domain name | IPv4 only; no A record → "DNS resolution failed"; use the server's own name, never the shared record name |
|
| Interval and threshold | 30 s default or 10 s fast (extra cost); failure threshold 1–10, default 3 | |
| Fixed at creation | Type, interval, string matching, latency measurement, "specify endpoint by" | Recreate, don't edit |
| Checker Regions | 8 selectable; a custom list needs at least 3; checker count not published ⚠️ unverified (course: about 15) | |
| Firewall | Allow ROUTE53_HEALTHCHECKS ranges (ip-ranges.json) or prefix list com.amazonaws.<region>.route53-healthchecks |
Checkers live on the internet |
| Private endpoints | Not reachable → CLOUDWATCH_METRIC check on an alarm (same account, standard resolution, no metric math, no M-out-of-N); reads metric data, so SetAlarmState can't trip it; InsufficientDataHealthStatus = Healthy, Unhealthy or LastKnownStatus |
Private targets need an alarm |
| Calculated checks | At least N, all (AND) or one or more (OR) children; NOT = invert a check; no nesting; child limit ⚠️ unverified: 256 (API) vs 255 (quotas page) | |
| Disabled vs inverted | Disabled = always healthy (still billed); inverted = flips the status | Disabled is healthy |
| Failover outcomes | Primary healthy → primary; primary down, secondary up → secondary; both down → primary; a primary with no check (and no EvaluateTargetHealth) never fails over |
Both down? Primary answers |
| Failover alias records | Must set EvaluateTargetHealth: true, except an alias to CloudFront (can't set it) |
|
| All records unhealthy | Group treated as all healthy; multivalue still returns up to 8 | |
EvaluateTargetHealth on ALB/NLB |
Healthy only if every target group with targets has a healthy target; an empty target group also counts as unhealthy, even next to a healthy one | |
EvaluateTargetHealth elsewhere |
Not allowed for CloudFront; no benefit for S3, API Gateway, VPC endpoints, Global Accelerator, OpenSearch, VPC Lattice (use your own health check); with a health check too, both must be healthy | |
| Metrics | HealthCheckStatus, HealthCheckPercentageHealthy in CloudWatch us-east-1 only |
|
| Static maintenance page | Secondary alias to an S3 website (HTTP only; CloudFront in front for HTTPS, and the secondary alias to the distribution has EvaluateTargetHealth: false) |
Weighted routing for blue green releases
| Topic | Current facts | Memory hook |
|---|---|---|
| Setup | Two weighted records, same name and type, SetIdentifier blue / green |
|
| Weights | 0–255, relative; 0 = no answers; all 0 = equal shares | Weights are shares |
| Shift and rollback | One atomic UPSERT batch per step (100/0 → 90/10 → 50/50 → 0/100); rollback = green to 0, effective after a TTL plus client caching |
Rollback waits a TTL |
| Group TTL | One TTL for all members (last value set wins); 60 s for non-alias members next to ELB aliases | |
| Zero-weight records with health checks | Used only when all non-zero records are unhealthy | |
| Empty green target group | ALB alias with EvaluateTargetHealth counts as unhealthy until targets register |
|
| JVM DNS cache ⚠️ | networkaddress.cache.ttl = 5 s (security property: java.security or Security.setProperty, not -D; older guidance, still in the RDS User Guide for Multi-AZ failover: no more than 60 s, which 5 s meets) |
|
| Better tools inside one endpoint | ALB weighted target groups, Lambda alias weights, API Gateway canary, CodeDeploy, Beanstalk traffic splitting | Same endpoint, no DNS |
Numbers to know
| Item | Value | Note |
|---|---|---|
| Name servers per hosted zone | 4 | From the zone's NS record |
| Hosted zone price | $0.50/month for each of the first 25; $0.10/month after | Deleted within 12 h of creation: no charge |
| Hosted zones per account | 500 | Adjustable |
| Records per hosted zone | 10,000 | Adjustable; extra charge above 10,000 |
| VPCs per private hosted zone | 300 | |
| Supported record types | 17 ⚠️ | HTTPS, SSHFP, SVCB, TLSA added 2024-10-30 |
| Change propagation | Generally within 60 s | GetChange → INSYNC |
| SOA TTLs | Record TTL 900 s; minimum TTL 86,400 s | Negative caching uses the lower one |
| NS record TTL | 172,800 s (2 days) | 60–900 s during a DNS migration |
| Change batch size | 1,000 ResourceRecord elements; 32,000 value characters |
UPSERT counts twice |
| API request rate ⚠️ | 50 burst, 10 per second sustained | Account level and per action (older docs: 5 per second) |
| Change throughput ⚠️ | 1,500 changes burst, 100 per second | UPSERT = 2 tokens |
CreateHealthCheck rate ⚠️ |
1 every 2 s | Refill 0.5 per second (older docs: 1,000 per 24 h) |
| Weight range | 0–255 | Relative |
| Weighted, latency, geolocation, multivalue or IP-based records per name/type | 100 | |
| Geoproximity records per name/type | 30 | |
| Multivalue answer | Up to 8 healthy records | Up to 8 unhealthy if all fail |
| IP-based CIDR lengths | IPv4 /1–/24; IPv6 /1–/48 | * = default location |
| CIDR collections | 5 per account; 1,000 blocks per collection | Adjustable |
| Healthy threshold | More than 18 % of checkers | |
| HTTP/HTTPS check timing | 4 s to connect + 2 s to respond | TCP: 10 s to connect |
| Request interval and failure threshold | 30 s (default) or 10 s; threshold 1–10, default 3 | 10 s costs extra |
| Calculated health check children | ⚠️ unverified: 256 (API) / 255 (quotas page) | AWS pages disagree; don't rely on it |
| Active health checks per account | 200 | Adjustable |
| Health check price | $0.50/month AWS endpoint; $0.75/month non-AWS | First 50 AWS-endpoint checks free; optional features extra |
| Traffic Flow policy record | $50/month | |
| Standard query price | $0.40 per million (first billion per month) | Alias queries to AWS resources: free |
| JVM DNS cache TTL ⚠️ | 5 s | networkaddress.cache.ttl (AWS SDK for Java guide; RDS failover guide: ≤ 60 s) |
Decision rules
- If you see a domain registered elsewhere that must use Route 53, think public hosted zone + registrar name servers set to the zone's 4 NS values.
- If you see the apex (
example.com) pointing at an ALB, CloudFront, API Gateway or S3 website, think aliasA/AAAA. - If you see "lowest DNS cost" for an AWS target, think alias (free queries), not
CNAME. - If you see an EC2 instance name or RDS endpoint as the target, think Elastic IP
Arecord orCNAMEbelow the apex. - If you see clients using an old IP long after a change, think TTL: lower it one old-TTL period ahead.
- If you see a new name still resolving as missing, think negative caching (SOA TTL 900 s).
- If you see
PriorRequestNotComplete, think wait-and-retry and batched changes. - If you see "a pipeline may change only one record", think record-name, type and action condition keys.
- If you see "fastest Region for each user", think latency records +
EvaluateTargetHealth. - If you see per-country content or licensing, think geolocation + default record.
- If you see "shift users towards one Region by distance", think geoproximity bias.
- If you see "route one ISP's IP ranges", think IP-based routing (CIDR collection).
- If you see "several healthy IPs, no load balancer", think multivalue answer.
- If you see "standby site or static page when the primary fails", think failover records + health check (or
EvaluateTargetHealth). - If you see a health check for a private-IP resource, think CloudWatch alarm health check.
- If you see a failing check on a working site, think security group (prefix list
com.amazonaws.<region>.route53-healthchecks), SNI, or a status outside 2xx/3xx. - If you see "force traffic away without editing records", think invert the health check.
- If you see "10 % to a new stack behind another load balancer", think weighted records.
- If you see "shift versions behind one ALB without DNS caching", think ALB weighted target groups.
- If you see Java clients ignoring a DNS change, think
networkaddress.cache.ttl= 5 s.
Memory hooks
- Apex needs alias; a CNAME lives below the apex.
- Alias is free, fresh and apex-friendly.
- A CNAME owns its name alone.
- Lower the TTL yesterday, change the record today.
- Missing names are cached too (15 minutes by default).
- One batch, all or nothing.
- Latency is fastest, not nearest; geolocation is where, not how far; geoproximity is distance with a bias.
- Default
*or no answer. - Eight healthy answers, still no load balancer.
- 18 % says healthy; 4 + 2 seconds for HTTP, 10 for TCP.
- Checkers live on the internet: private targets need an alarm.
- Disabled stays healthy; inverted flips the verdict.
- Both down? The primary answers.
- Weights are shares, not percentages.
- Every DNS switch waits a TTL.