AWS Route 53: DNS, Routing Policies, and Health Checks
Route 53 is AWS's DNS service — authoritative DNS for your domains, health checking, and traffic routing logic. Beyond simple A records, Route 53 provides routing policies that enable failover, latency-based routing, weighted traffic splits, and geolocation routing. This covers Route 53 hosted zones, record types, routing policies (simple, failover, latency, weighted, geolocation, geoproximity, multivalue), health checks, private hosted zones for VPC-internal DNS, resolver rules for hybrid environments, and the operational patterns for zero-downtime DNS changes.

DNS is often treated as a solved problem — create a few records and move on. Route 53 makes it worth thinking more carefully: health-check-driven failover, latency-based routing to the nearest region, and traffic weighting for canary deployments are all built into the DNS layer, without requiring changes to load balancers or application code.
Hosted Zones
A hosted zone is a container for DNS records for a domain. Route 53 supports two types:
Public hosted zone: responds to DNS queries from the public internet. When you register a domain or delegate a subdomain, you point its name servers to Route 53's name servers for the zone.
Private hosted zone: responds to DNS queries from within one or more VPCs. Use private zones for internal service discovery, private endpoints, and overriding public DNS records within your VPC.
1# Create a public hosted zone
2aws route53 create-hosted-zone \
3 --name codingprotocols.com \
4 --caller-reference $(date +%s)
5
6# Create a private hosted zone associated with a VPC
7aws route53 create-hosted-zone \
8 --name prod.internal \
9 --caller-reference $(date +%s)-private \
10 --hosted-zone-config Comment="Internal VPC DNS",PrivateZone=true \
11 --vpc VPCRegion=us-east-1,VPCId=vpc-abc123Record Types
| Record Type | Purpose | Example |
|---|---|---|
| A | Maps hostname to IPv4 address | api.example.com → 203.0.113.10 |
| AAAA | Maps hostname to IPv6 address | api.example.com → 2001:db8::1 |
| CNAME | Alias to another hostname | www.example.com → example.com |
| ALIAS | Route 53-specific — maps to AWS resources | example.com → ALB DNS name |
| MX | Mail server routing | Priority + mail server hostname |
| TXT | Text records (SPF, DKIM, domain verification) | Arbitrary text |
| NS | Name server delegation | Points to authoritative name servers |
| SRV | Service locator (rarely used on AWS) | Priority, weight, port, target |
ALIAS vs CNAME
ALIAS is Route 53's extension to DNS. Use it to point a zone apex (example.com) or any record to an AWS resource — ALB, CloudFront distribution, Elastic Beanstalk environment, S3 website bucket, or another Route 53 record. DNS resolvers see ALIAS records as A/AAAA records.
CNAME cannot be used at the zone apex (example.com with no subdomain). www.example.com CNAME example.com is valid, but example.com CNAME something.else.com is not — the DNS spec prohibits CNAME at the apex.
1# ALIAS record — zone apex pointing to CloudFront
2aws route53 change-resource-record-sets \
3 --hosted-zone-id Z123456789 \
4 --change-batch '{
5 "Changes": [{
6 "Action": "UPSERT",
7 "ResourceRecordSet": {
8 "Name": "codingprotocols.com",
9 "Type": "A",
10 "AliasTarget": {
11 "HostedZoneId": "Z2FDTNDATAQYW2",
12 "DNSName": "d111111abcdef8.cloudfront.net",
13 "EvaluateTargetHealth": false
14 }
15 }
16 }]
17 }'The CloudFront hosted zone ID Z2FDTNDATAQYW2 is fixed — it's the same for all CloudFront distributions globally. ALBs, API Gateways, and other AWS services each have their own hosted zone IDs that vary by region.
Routing Policies
Simple
Returns one or more IP addresses (for multivalue) or a single value. No health checking. Use for single-endpoint routing.
Weighted
Routes a percentage of traffic to each endpoint. Use for blue/green deployments, canary rollouts, and A/B testing:
1# 90% of traffic to production, 10% to canary
2aws route53 change-resource-record-sets \
3 --hosted-zone-id Z123456789 \
4 --change-batch '{
5 "Changes": [
6 {
7 "Action": "UPSERT",
8 "ResourceRecordSet": {
9 "Name": "api.codingprotocols.com",
10 "Type": "A",
11 "SetIdentifier": "production",
12 "Weight": 90,
13 "AliasTarget": {
14 "HostedZoneId": "Z35SXDOTRQ7X7K",
15 "DNSName": "prod-alb.us-east-1.elb.amazonaws.com",
16 "EvaluateTargetHealth": true
17 }
18 }
19 },
20 {
21 "Action": "UPSERT",
22 "ResourceRecordSet": {
23 "Name": "api.codingprotocols.com",
24 "Type": "A",
25 "SetIdentifier": "canary",
26 "Weight": 10,
27 "AliasTarget": {
28 "HostedZoneId": "Z35SXDOTRQ7X7K",
29 "DNSName": "canary-alb.us-east-1.elb.amazonaws.com",
30 "EvaluateTargetHealth": true
31 }
32 }
33 }
34 ]
35 }'Weight values are relative ratios — 90 and 10 produce the same distribution as 9 and 1. To send all traffic to one record, set the other's weight to 0 (the zero-weight record stays in the hosted zone but receives no traffic).
Failover
Routes traffic to a primary endpoint when it's healthy, and to a secondary when the primary is unhealthy. Requires health checks on the primary (required) and optionally on the secondary.
1# Health check for primary endpoint
2aws route53 create-health-check \
3 --caller-reference $(date +%s)-primary \
4 --health-check-config '{
5 "IPAddress": "203.0.113.10",
6 "Port": 443,
7 "Type": "HTTPS",
8 "ResourcePath": "/health",
9 "FullyQualifiedDomainName": "api.codingprotocols.com",
10 "RequestInterval": 30,
11 "FailureThreshold": 3
12 }'
13
14# Primary record
15aws route53 change-resource-record-sets \
16 --hosted-zone-id Z123456789 \
17 --change-batch '{
18 "Changes": [{
19 "Action": "UPSERT",
20 "ResourceRecordSet": {
21 "Name": "api.codingprotocols.com",
22 "Type": "A",
23 "SetIdentifier": "primary",
24 "Failover": "PRIMARY",
25 "HealthCheckId": "abc-health-check-id",
26 "AliasTarget": {
27 "HostedZoneId": "Z35SXDOTRQ7X7K",
28 "DNSName": "prod-alb.us-east-1.elb.amazonaws.com",
29 "EvaluateTargetHealth": true
30 }
31 }
32 }]
33 }'Failover timing: health checks run every 10 or 30 seconds (configurable). With a FailureThreshold of 3 and 30-second intervals, Route 53 marks the endpoint unhealthy after 3 consecutive failures — 90 seconds. DNS TTL affects how quickly clients see the failover (clients cache the old answer until TTL expires). For fast failover, set the record TTL to 60 seconds or less.
Latency
Routes traffic to the AWS region with the lowest network latency for the requesting client. Route 53 measures latency from a large set of client networks and routes to the best-performing region.
1aws route53 change-resource-record-sets \
2 --hosted-zone-id Z123456789 \
3 --change-batch '{
4 "Changes": [
5 {
6 "Action": "UPSERT",
7 "ResourceRecordSet": {
8 "Name": "api.codingprotocols.com",
9 "Type": "A",
10 "SetIdentifier": "us-east-1",
11 "Region": "us-east-1",
12 "AliasTarget": {
13 "HostedZoneId": "Z35SXDOTRQ7X7K",
14 "DNSName": "prod-alb-us-east-1.elb.amazonaws.com",
15 "EvaluateTargetHealth": true
16 }
17 }
18 },
19 {
20 "Action": "UPSERT",
21 "ResourceRecordSet": {
22 "Name": "api.codingprotocols.com",
23 "Type": "A",
24 "SetIdentifier": "eu-west-1",
25 "Region": "eu-west-1",
26 "AliasTarget": {
27 "HostedZoneId": "Z32O12XQLNTSW2",
28 "DNSName": "prod-alb-eu-west-1.elb.amazonaws.com",
29 "EvaluateTargetHealth": true
30 }
31 }
32 }
33 ]
34 }'Latency routing works with EvaluateTargetHealth=true on the alias — if the ALB in a region is unhealthy, Route 53 routes to the next-best region automatically.
Geolocation and Geoproximity
Geolocation: routes based on the geographic location of the DNS resolver (approximates user location). Can target by continent, country, or US state. A default record catches all locations not explicitly targeted.
Geoproximity: routes based on geographic location of both users and resources, with an optional bias that expands or shrinks the geographic area served by a resource. Use geoproximity when you want to shift traffic boundaries between regions (e.g., have eu-west-1 serve more of the Eastern US during a eu-central-1 incident).
Multivalue Answer
Returns up to 8 healthy IP addresses to the DNS resolver. The resolver picks one (usually randomly). Requires health checks on each record. Not a substitute for load balancing — the resolver selects from the returned IPs without traffic distribution guarantees.
Health Checks
Route 53 health checks monitor endpoints from distributed health checker locations globally. Types:
Endpoint health check: monitors a specific IP address or domain. Checks via HTTP, HTTPS, or TCP. Can verify a specific path and optionally check for a string in the response body.
Calculated health check: combines the status of multiple other health checks. Use to model "at least 2 of 3 regions healthy" logic.
CloudWatch alarm health check: marks healthy/unhealthy based on a CloudWatch alarm state. Useful for complex health logic that doesn't map to a simple HTTP check.
1# Advanced health check — HTTPS with string match
2aws route53 create-health-check \
3 --caller-reference $(date +%s) \
4 --health-check-config '{
5 "FullyQualifiedDomainName": "api.codingprotocols.com",
6 "Port": 443,
7 "Type": "HTTPS_STR_MATCH",
8 "SearchString": "\"status\":\"healthy\"",
9 "ResourcePath": "/health",
10 "RequestInterval": 10,
11 "FailureThreshold": 2,
12 "EnableSNI": true,
13 "Regions": ["us-east-1", "eu-west-1", "ap-southeast-1"]
14 }'RequestInterval of 10 seconds (fast health check) vs 30 seconds (standard). Fast health checks cost 3× more. Use fast health checks for production services where you need failover in under 30 seconds.
Regions: the AWS regions from which health checkers make requests. Specifying 3 regions means health checkers in those regions all make the request — the endpoint is healthy if the majority of specified regions report healthy (or all, depending on failure threshold configuration).
Private Hosted Zones
Private hosted zones resolve DNS queries only within associated VPCs. Use for:
- Internal service discovery:
payments-api.prod.internal → internal ALB DNS name - Overriding public DNS records:
api.codingprotocols.com → private IPwithin the VPC (private zone takes precedence over public zone for associated VPCs) - Endpoint resolution: VPC interface endpoints have private DNS names; a private hosted zone can alias these
1# Associate additional VPCs with a private hosted zone
2aws route53 associate-vpc-with-hosted-zone \
3 --hosted-zone-id Z123456789 \
4 --vpc VPCRegion=us-east-1,VPCId=vpc-def456
5
6# Create an internal service record in the private zone
7aws route53 change-resource-record-sets \
8 --hosted-zone-id Z123456789 \
9 --change-batch '{
10 "Changes": [{
11 "Action": "UPSERT",
12 "ResourceRecordSet": {
13 "Name": "payments-api.prod.internal",
14 "Type": "A",
15 "AliasTarget": {
16 "HostedZoneId": "Z35SXDOTRQ7X7K",
17 "DNSName": "internal-alb.us-east-1.elb.amazonaws.com",
18 "EvaluateTargetHealth": true
19 }
20 }
21 }]
22 }'Private zone vs Cloud Map: Cloud Map provides service discovery with both DNS and API-based lookup. For Kubernetes-based service discovery, use CoreDNS (built into EKS). Private hosted zones in Route 53 are right for infrastructure-level DNS (ALBs, RDS endpoints, VPC endpoints) rather than pod-level service discovery.
Route 53 Resolver
Route 53 Resolver provides DNS resolution within and between VPCs, and between VPCs and on-premises networks.
Inbound endpoints: receive DNS queries from your on-premises network (forwarded via your on-premises DNS server) and resolve them using Route 53 hosted zones.
Outbound endpoints: forward DNS queries for specific domains (e.g., corp.example.internal) from your VPC to your on-premises DNS servers.
1# Create an outbound resolver endpoint
2aws route53resolver create-resolver-endpoint \
3 --creator-request-id $(date +%s) \
4 --direction OUTBOUND \
5 --ip-addresses SubnetId=subnet-private-1a SubnetId=subnet-private-1b \
6 --security-group-ids sg-resolver \
7 --name prod-outbound-endpoint
8
9# Create a resolver rule to forward queries for corp.example.internal to on-premises DNS
10aws route53resolver create-resolver-rule \
11 --creator-request-id $(date +%s) \
12 --rule-type FORWARD \
13 --domain-name corp.example.internal \
14 --name forward-to-onprem \
15 --target-ips Ip=10.0.0.2,Port=53 Ip=10.0.0.3,Port=53 \
16 --resolver-endpoint-id <endpoint-id>Resolver rules are associated with VPCs and shared via AWS RAM to other accounts.
Operational Patterns
Zero-Downtime DNS Cutover
When migrating a domain or service endpoint:
-
Lower TTL before migration: days before the cutover, lower the record's TTL to 60–300 seconds. Wait for the old high TTL to expire from resolver caches (wait at least as long as the old TTL).
-
Verify new endpoint: confirm the new endpoint is fully operational before changing DNS.
-
Update the record: change the DNS record to point to the new endpoint.
-
Monitor: watch error rates for the duration of the old TTL (clients still sending to old endpoint gradually migrate as their cached record expires).
-
Raise TTL: after traffic has fully migrated and the new endpoint is stable, raise the TTL back to your standard (300–3600 seconds).
1# Step 1 — Lower TTL 24 hours before migration
2aws route53 change-resource-record-sets \
3 --hosted-zone-id Z123456789 \
4 --change-batch '{
5 "Changes": [{
6 "Action": "UPSERT",
7 "ResourceRecordSet": {
8 "Name": "api.codingprotocols.com",
9 "Type": "A",
10 "TTL": 60,
11 "ResourceRecords": [{"Value": "203.0.113.10"}]
12 }
13 }]
14 }'Delegation for Subdomain Control
Delegate a subdomain to a different hosted zone (or a different team's hosted zone):
1# In the parent zone — add NS records for the subdomain
2# pointing to the child zone's name servers
3aws route53 change-resource-record-sets \
4 --hosted-zone-id Z123456789 \
5 --change-batch '{
6 "Changes": [{
7 "Action": "UPSERT",
8 "ResourceRecordSet": {
9 "Name": "staging.codingprotocols.com",
10 "Type": "NS",
11 "TTL": 172800,
12 "ResourceRecords": [
13 {"Value": "ns-1234.awsdns-12.com."},
14 {"Value": "ns-5678.awsdns-34.net."},
15 {"Value": "ns-9012.awsdns-56.org."},
16 {"Value": "ns-3456.awsdns-78.co.uk."}
17 ]
18 }
19 }]
20 }'Frequently Asked Questions
How long does Route 53 failover take?
End-to-end failover time depends on:
- Health check interval: 10s (fast) or 30s (standard)
- Failure threshold: number of consecutive failures before marking unhealthy (default 3)
- Record TTL: how long clients cache the DNS response
Worst case with standard settings: 30s × 3 = 90s to mark unhealthy + TTL (if 300s) = 390s. With fast health checks, 10s TTL records: 10s × 3 = 30s + 10s TTL ≈ 40s end-to-end.
For critical services, set fast health checks + TTL ≤ 60 seconds. At 60-second TTL, accept that some clients will hold stale records for up to 60 seconds.
Can Route 53 route traffic based on request content (path, headers)?
No — DNS resolution happens before the HTTP request and has no visibility into request content. Path-based and header-based routing requires a load balancer (ALB listener rules) or API Gateway, not DNS.
Route 53 can route based on: client geographic location, observed latency to AWS regions, endpoint health, and weighted ratios. For everything else, route to a load balancer and do content-based routing there.
How do I handle Route 53 in a multi-account AWS organization?
Use Route 53 Resolver Rules and RAM (Resource Access Manager) to share resolver rules across accounts. For hosted zones, associate VPCs from other accounts with a private hosted zone using associate-vpc-with-hosted-zone (requires cross-account authorization).
For centralized DNS management, maintain the public hosted zone in a shared-services account and delegate subdomains to team-specific accounts. Teams manage their own subdomains independently without access to the root zone.
For VPC-internal DNS with Route 53 private hosted zones complementing VPC endpoint private DNS, see AWS VPC Design for EKS: Subnets, NAT, and Security Groups. For Cloud Map as a service discovery alternative for ECS services, see AWS ECS vs EKS: Choosing the Right Container Orchestrator on AWS.
Planning a multi-region active-active architecture with Route 53 latency routing, migrating a domain with zero downtime, or setting up hybrid DNS resolution between on-premises and AWS? Talk to us at Coding Protocols — we help platform teams design DNS architectures that enable failover, latency routing, and split-horizon resolution without disrupting services.


