Introduction to Amazon Route 53
Amazon Route 53 is a highly available and scalable cloud Domain Name System (DNS) web service designed to give developers and businesses an extremely reliable and cost-effective way to route end users to Internet applications. The name "Route 53" is a reference to port 53, the traditional port used for DNS requests. As a core service within the AWS ecosystem, Route 53 combines DNS routing with health checking and domain registration, making it a one-stop solution for managing how users reach your applications.
Whether you are hosting a simple static website on Amazon S3, running a multi-region microservices architecture behind Elastic Load Balancers, or migrating legacy infrastructure to the cloud, Route 53 provides the building blocks to ensure traffic reaches the right destination quickly and reliably. It integrates natively with other AWS services such as CloudFront, API Gateway, EC2, and Elastic Beanstalk, while still supporting non-AWS endpoints.
Why Route 53 Matters
DNS is often described as the phonebook of the internet, but in modern cloud architectures it is much more than that. DNS is the first decision point for every user request, and the quality of that decision directly impacts latency, availability, and security. Route 53 matters because it elevates DNS from a simple name-resolution service into an intelligent traffic-management layer.
Key Benefits
- High Availability: Route 53 is built on a global network of DNS servers distributed across many AWS regions, providing low-latency responses and automatic failover.
- Health Checks: You can configure health checks that monitor the status of your endpoints and automatically route traffic away from unhealthy resources.
- Advanced Routing Policies: Beyond simple DNS resolution, Route 53 supports latency-based, geolocation, geoproximity, weighted, and failover routing.
- Domain Registration: Route 53 is an ICANN-accredited registrar, allowing you to purchase and manage domains directly within AWS.
- Tight AWS Integration: Alias records let you map domain names to AWS resources like CloudFront distributions, S3 buckets, and load balancers without incurring per-query charges for those mappings.
- Security: Integration with AWS IAM, support for DNSSEC, and private hosted zones for internal VPC resolution provide robust security controls.
Core Concepts
Before diving into configuration, it is important to understand the foundational concepts that govern how Route 53 operates.
Hosted Zones
A hosted zone is a container for records that define how you want to route traffic for a specific domain and its subdomains. There are two types of hosted zones:
- Public Hosted Zone: Used for internet-facing domains accessible by anyone on the internet.
- Private Hosted Zone: Used for domains accessible only within one or more Amazon VPCs, ideal for internal services.
Record Types
Route 53 supports a wide variety of DNS record types, including A, AAAA, CNAME, MX, TXT, NS, SOA, SRV, CAA, and the AWS-specific Alias record. The Alias record is particularly powerful because it lets you point to AWS resources while avoiding the cost and limitation of standard CNAME records at the zone apex.
Routing Policies
Routing policies determine how Route 53 responds to DNS queries when multiple records share the same name and type. The available policies are:
- Simple: Returns a single resource.
- Weighted: Distributes traffic across multiple resources based on assigned weights.
- Latency: Routes users to the AWS region with the lowest latency.
- Failover: Routes traffic to a primary resource and switches to a secondary resource when the primary is unhealthy.
- Geolocation: Routes based on the geographic location of the user.
- Geoproximity: Routes based on the geographic location of resources and an optional bias.
- Multivalue Answer: Returns multiple IP addresses, similar to simple round-robin with health checks.
- IP-based Routing: Routes based on the specific CIDR blocks of the source IP.
Setting Up Route 53: A Complete Walkthrough
In this section, we will walk through a complete setup scenario. We will register a domain (or assume you already own one), create a public hosted zone, configure records, set up health checks, and implement a routing policy. We will use the AWS Management Console, the AWS CLI, and Infrastructure as Code with Terraform.
Prerequisites
- An active AWS account with appropriate IAM permissions (route53:*, ec2:DescribeInstances, elasticloadbalancing:DescribeLoadBalancers).
- A registered domain name. You can register one through Route 53 or transfer an existing domain from another registrar.
- AWS CLI installed and configured with credentials.
- Terraform installed (optional, for the IaC section).
Step 1: Register or Transfer a Domain
If you do not already own a domain, you can register one directly in Route 53. Navigate to the Route 53 console, choose "Registered domains," and click "Register domain." Search for your desired name, select a top-level domain (TLD), and complete the purchase. AWS automatically creates a hosted zone for newly registered domains.
If you already own a domain through another registrar, you have two options: transfer the registration to Route 53, or keep the registration where it is and simply update the domain's name servers to point to Route 53. The second option is more common and is what we will use in this tutorial.
Step 2: Create a Public Hosted Zone
A hosted zone holds the DNS records for your domain. To create one using the AWS CLI, use the following command:
aws route53 create-hosted-zone \
--name example.com \
--caller-reference $(date +%s) \
--hosted-zone-config Comment="Primary hosted zone for example.com",PrivateZone=false
The response will include a DelegationSet containing four name servers. These are the authoritative name servers for your domain. You must update your domain registrar to use these name servers instead of the existing ones. Until this change propagates (typically within 24 to 48 hours), DNS queries for your domain will continue to be resolved by the previous DNS provider.
Step 3: Create Basic DNS Records
Once the hosted zone exists, you can start adding records. The most common record you will create is an A record pointing to a web server or load balancer. Because Route 53 uses a change-batch model for record creation, you define changes in a JSON document.
Create a file named change-batch.json:
{
"Comment": "Create A record for www subdomain",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "www.example.com.",
"Type": "A",
"TTL": 300,
"ResourceRecords": [
{ "Value": "203.0.113.42" }
]
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "example.com.",
"Type": "A",
"TTL": 300,
"ResourceRecords": [
{ "Value": "203.0.113.42" }
]
}
}
]
}
Apply the change batch with the following command, replacing HOSTED_ZONE_ID with the ID returned from the previous step:
aws route53 change-resource-record-sets \
--hosted-zone-id HOSTED_ZONE_ID \
--change-batch file://change-batch.json
Route 53 returns a change ID that you can use to track the status of the change. You can poll the status with:
aws route53 get-change --id CHANGE_ID
The status will transition from PENDING to INSYNC, typically within a few seconds.
Step 4: Using Alias Records for AWS Resources
When pointing your domain to AWS resources such as an Application Load Balancer, a CloudFront distribution, or an S3 bucket configured for static website hosting, you should use Alias records instead of standard A or CNAME records. Alias records are free for queries against AWS resources and work at the zone apex, which CNAME records cannot.
Here is an example of creating an Alias record that points to an Application Load Balancer:
{
"Comment": "Alias record to ALB",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "app.example.com.",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z35SXDOTRQ7X7K",
"DNSName": "dualstack.my-load-balancer-1234567890.us-east-1.elb.amazonaws.com.",
"EvaluateTargetHealth": true
}
}
}
]
}
The HostedZoneId in the AliasTarget refers to the hosted zone of the load balancer, not your own hosted zone. AWS publishes these canonical hosted zone IDs in the documentation for each service. The EvaluateTargetHealth flag tells Route 53 to consider the health of the load balancer when responding to queries.
Step 5: Configure Health Checks
Health checks allow Route 53 to monitor the availability of your endpoints and route traffic accordingly. You can create health checks that monitor IP addresses, domain names, CloudWatch alarms, or the health of other health checks (calculated health checks).
To create a health check that monitors an endpoint over HTTPS:
aws route53 create-health-check \
--caller-reference $(date +%s) \
--health-check-config '
{
"Type": "HTTPS",
"FullyQualifiedDomainName": "www.example.com",
"IPAddress": "203.0.113.42",
"Port": 443,
"ResourcePath": "/health",
"RequestInterval": 30,
"FailureThreshold": 3,
"MeasureLatency": true
}'
This health check will send an HTTPS request to https://203.0.113.42:443/health every 30 seconds, using the Host header www.example.com. If three consecutive checks fail, the health check is marked unhealthy. You can then associate this health check with a record to enable automatic failover.
Step 6: Implement a Failover Routing Policy
Failover routing is one of the most common use cases for Route 53 health checks. In this scenario, you have a primary endpoint and a secondary (backup) endpoint. Route 53 sends all traffic to the primary as long as it is healthy. When the primary fails its health check, traffic is automatically redirected to the secondary.
{
"Comment": "Failover routing configuration",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "api.example.com.",
"Type": "A",
"SetIdentifier": "primary",
"Failover": "PRIMARY",
"HealthCheckId": "abc12345-6789-0abc-def1-234567890abc",
"TTL": 60,
"ResourceRecords": [
{ "Value": "203.0.113.10" }
]
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "api.example.com.",
"Type": "A",
"SetIdentifier": "secondary",
"Failover": "SECONDARY",
"TTL": 60,
"ResourceRecords": [
{ "Value": "198.51.100.20" }
]
}
}
]
}
Notice that both records share the same name and type but have different SetIdentifier values. This is required whenever you use any routing policy other than simple. The primary record references the health check ID, while the secondary does not need one because it acts as the fallback.
Step 7: Weighted Routing for Canary Deployments
Weighted routing is invaluable for canary deployments, A/B testing, and gradual migrations. You assign a weight to each record, and Route 53 distributes traffic proportionally. For example, if you want to send 95% of traffic to your stable version and 5% to a new version, configure two records with weights of 95 and 5 respectively.
{
"Comment": "Weighted routing for canary deployment",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "service.example.com.",
"Type": "A",
"SetIdentifier": "stable-v1",
"Weight": 95,
"TTL": 60,
"ResourceRecords": [
{ "Value": "203.0.113.50" }
]
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "service.example.com.",
"Type": "A",
"SetIdentifier": "canary-v2",
"Weight": 5,
"TTL": 60,
"ResourceRecords": [
{ "Value": "203.0.113.60" }
]
}
}
]
}
To gradually shift traffic, update the weights over time. For instance, move from 95/5 to 80/20, then 50/50, and finally 0/100 once you are confident in the new version. Always associate health checks with weighted records so that traffic is automatically removed from unhealthy endpoints.
Step 8: Latency-Based Routing for Global Applications
If your application is deployed across multiple AWS regions, latency-based routing ensures users are directed to the region that provides the fastest response. Route 53 maintains a database of latency data between regions and user locations, and it selects the record with the lowest latency for each query.
{
"Comment": "Latency routing across regions",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "global.example.com.",
"Type": "A",
"SetIdentifier": "us-east",
"Region": "us-east-1",
"TTL": 60,
"ResourceRecords": [
{ "Value": "203.0.113.100" }
]
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "global.example.com.",
"Type": "A",
"SetIdentifier": "eu-west",
"Region": "eu-west-1",
"TTL": 60,
"ResourceRecords": [
{ "Value": "198.51.100.100" }
]
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "global.example.com.",
"Type": "A",
"SetIdentifier": "ap-southeast",
"Region": "ap-southeast-1",
"TTL": 60,
"ResourceRecords": [
{ "Value": "192.0.2.100" }
]
}
}
]
}
Combine latency routing with health checks and failover records to create a resilient multi-region architecture. If the closest region becomes unhealthy, Route 53 will route the user to the next healthiest region.
Private Hosted Zones for Internal DNS
Private hosted zones enable you to maintain custom DNS names for resources within your VPCs without exposing them to the public internet. This is essential for microservice architectures where internal services communicate using friendly domain names rather than IP addresses.
To create a private hosted zone and associate it with a VPC:
aws route53 create-hosted-zone \
--name internal.example.com \
--caller-reference $(date +%s) \
--hosted-zone-config PrivateZone=true \
--vpc VPCRegion=us-east-1,VPCId=vpc-0abc123def456
Once created, you can add records just as you would for a public hosted zone. For example, you might create an A record for database.internal.example.com pointing to the private IP of an RDS instance or an Aurora cluster endpoint. Resources within the associated VPC will resolve these names automatically, while external queries will receive no response.
If you need to associate the private hosted zone with additional VPCs, including VPCs in other AWS accounts, use the associate-vpc-with-hosted-zone command. For cross-account associations, you must first create a VPC authorization in the account that owns the hosted zone.
Infrastructure as Code with Terraform
Managing DNS through the console or CLI is fine for small setups, but production environments benefit from Infrastructure as Code. Terraform provides an excellent Route 53 provider that allows you to version-control and reproduce your DNS configuration.
Here is a complete Terraform example that creates a hosted zone, an Alias record pointing to a load balancer, a health check, and a failover routing configuration:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
# Public Hosted Zone
resource "aws_route53_zone" "primary" {
name = "example.com"
comment = "Primary hosted zone managed by Terraform"
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
# Alias record pointing to an Application Load Balancer
resource "aws_route53_record" "app" {
zone_id = aws_route53_zone.primary.zone_id
name = "app.example.com"
type = "A"
alias {
name = aws_lb.app.dns_name
zone_id = aws_lb.app.zone_id
evaluate_target_health = true
}
}
# Health check for the primary endpoint
resource "aws_route53_health_check" "primary" {
fqdn = "api.example.com"
port = 443
type = "HTTPS"
resource_path = "/health"
request_interval = 30
failure_threshold = 3
regions = ["us-east-1", "us-west-1", "eu-west-1"]
}
# Failover routing: primary record
resource "aws_route53_record" "api_primary" {
zone_id = aws_route53_zone.primary.zone_id
name = "api.example.com"
type = "A"
set_identifier = "primary"
failover_routing_policy {
type = "PRIMARY"
}
health_check_id = aws_route53_health_check.primary.id
ttl = 60
records = ["203.0.113.10"]
}
# Failover routing: secondary record
resource "aws_route53_record" "api_secondary" {
zone_id = aws_route53_zone.primary.zone_id
name = "api.example.com"
type = "A"
set_identifier = "secondary"
failover_routing_policy {
type = "SECONDARY"
}
ttl = 60
records = ["198.51.100.20"]
}
# Output the name servers
output "name_servers" {
value = aws_route53_zone.primary.name_servers
}
Run terraform init, terraform plan, and terraform apply to provision these resources. The name_servers output gives you the delegation set to configure at your domain registrar. Using Terraform ensures your DNS configuration is reproducible, reviewable, and safe from manual drift.
Best Practices
Use Alias Records for AWS Resources
Whenever you point a record to an AWS resource such as a load balancer, CloudFront distribution, S3 website endpoint, or API Gateway, use Alias records instead of CNAME records. Alias records incur no charge for queries, support the zone apex, and automatically track changes to the underlying resource's IP addresses.
Keep TTLs Reasonable
TTL (Time to Live) determines how long DNS resolvers cache your records. A TTL that is too high means changes take a long time to propagate, while a TTL that is too low increases query volume and cost. For records that change frequently, use a TTL of 60 seconds. For stable records, 300 to 3600 seconds is appropriate. When planning a migration, lower your TTLs 24 to 48 hours in advance so that changes propagate quickly.
Always Configure Health Checks for Critical Records
Health checks are the foundation of high availability in Route 53. For any record that serves production traffic, associate a health check and enable EvaluateTargetHealth on Alias records. This ensures that Route 53 stops sending traffic to endpoints that are unreachable, returning errors, or failing custom health endpoints.
Use Multiple Health Check Regions
By default, Route 53 performs health checks from multiple locations. You can further refine this by specifying the regions from which checks originate. Using at least three geographically diverse regions reduces false positives caused by transient network issues in a single location.
Implement DNSSEC for Security
DNSSEC adds cryptographic signatures to your DNS records, protecting users from DNS spoofing and cache poisoning attacks. Route 53 supports DNSSEC for both signing your hosted zone (DNSSEC signing) and validating responses from upstream name servers (DNSSEC validation). Enable DNSSEC signing on public hosted zones that serve sensitive applications.
Tag Your Resources
Apply consistent tags to your hosted zones and health checks. Tags such as Environment, Application, Owner, and ManagedBy help with cost allocation, auditing, and operational visibility, especially in large organizations with many AWS accounts.
Monitor with CloudWatch
Route 53 integrates with CloudWatch to provide metrics such as health check status, query counts, and latency. Create CloudWatch Alarms that notify your team when health checks fail or when query volumes spike unexpectedly. You can also use CloudWatch Logs to inspect DNS query patterns for troubleshooting.
Plan for Disaster Recovery
Design your DNS configuration with disaster recovery in mind. Use failover routing to define primary and secondary endpoints across different regions or even different cloud providers. Document the procedure for updating DNS records during a failover event, and test your failover regularly to ensure it works as expected under real conditions.
Avoid Overlapping Private Hosted Zones
When using private hosted zones, be careful not to create overlapping zones that could cause resolution conflicts. For example, having both example.com and internal.example.com as private hosted zones associated with the same VPC can lead to unpredictable behavior. Use a clear naming hierarchy and document which zone is authoritative for each subdomain.
Leverage Traffic Policies for Complex Routing
For advanced routing scenarios that combine multiple policies (such as latency-based routing with failover within each region), use Route 53 Traffic Policies. Traffic Policies provide a visual editor and versioning, making it easier to manage complex configurations than stacking individual records.
Conclusion
Amazon Route 53 is far more than a traditional DNS service. Its combination of global infrastructure, health checking, advanced routing policies, and deep AWS integration makes it a powerful tool for building highly available, performant, and resilient applications. By understanding the core concepts of hosted zones, record types, and routing policies, and by following best practices around Alias records, TTLs, health checks, and Infrastructure as Code, you can create a DNS architecture that scales with your application and gracefully handles failures. Whether you are running a single-region web application or a globally distributed microservices platform, Route 53 provides the flexibility and reliability needed to route your users to the right destination every time.