Route 53 Routing Policies
Amazon Route 53 is the AWS managed DNS (Domain Name System — the service that turns names like app.example.com into IP addresses) service. A routing policy is the rule Route 53 uses to decide which answer to return when many records share the same name. This is how you do A/B testing, send users to the closest Region, or fail over to a backup when something breaks. This page walks through each policy, when to reach for it, and the one gotcha that trips up almost everyone: DNS answers are cached, so routing changes are never truly instant.
How a routing policy fits in
When you create a record (say, an A record for www.example.com) you must choose a routing policy. With simple routing there is one answer and Route 53 always returns it. With every other policy you create multiple records with the same name and type, and the policy tells Route 53 how to pick among them per query. Resolvers (the DNS servers your users’ computers talk to) then cache that answer for the record’s TTL (Time To Live — how many seconds an answer may be reused before asking again).
Routing policies steer DNS answers. They do not proxy or move traffic themselves — once a client has an IP, Route 53 is out of the loop until the cached answer expires. That is why low TTLs and health checks matter so much.
The routing policies at a glance
| Policy | What it does | Classic use case | When NOT to use |
|---|---|---|---|
| Simple | Returns one record (or all values, randomly ordered) | A single endpoint with no logic | Any time you need health checks or steering |
| Weighted | Splits answers by a numeric weight | A/B testing, blue/green rollout | When you need exact per-user splits |
| Latency-based | Returns the Region with lowest network latency to the user | Multi-Region apps wanting speed | Single-Region apps |
| Geolocation | Routes by the user’s continent/country/state | Compliance, localized content | When latency, not geography, is the goal |
| Geoproximity | Routes by geographic distance, with an adjustable “bias” | Shifting traffic between Regions by region size | Simple cases (use latency instead) |
| Failover | Primary/secondary; secondary only on health-check failure | Disaster recovery (DR) | Active-active designs (use weighted/latency) |
| Multivalue answer | Returns up to 8 healthy records, randomized | Cheap client-side load spreading | True load balancing (use an ALB/NLB) |
Weighted routing — A/B and blue/green
Weighted routing assigns each record a weight from 0 to 255. Route 53 returns a record proportional to its share of the total weight. Two records weighted 90 and 10 send roughly 90% and 10% of resolutions to each. Setting a weight to 0 stops a record from being served (handy to drain a version).
When to use it: gradual rollouts (shift 5% of traffic to a new version, watch metrics, ramp up) or simple A/B experiments.
When NOT to use it: when you need a precise per-user split. Because of caching, the ratio is an approximation across many resolvers over time, not a coin flip per visitor.
Console steps:
- Open the Route 53 console, choose Hosted zones, and select your zone.
- Click Create record, enter the name (e.g.
app), choose type A. - Set Routing policy to Weighted, enter the value/alias, a Weight (e.g.
90), and a unique Record ID (e.g.prod-v1). - Repeat to add the second record with weight
10and a different Record ID.
CLI equivalent (CLI v2). Save this change batch and apply it:
aws route53 change-resource-record-sets \
--hosted-zone-id Z0123456789ABCDEFGHIJ \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "app.example.com",
"Type": "A",
"SetIdentifier": "prod-v1",
"Weight": 90,
"TTL": 60,
"ResourceRecords": [{ "Value": "203.0.113.10" }]
}
}]
}'
Output:
{
"ChangeInfo": {
"Id": "/change/C0987654321ZYXWVUTSRQ",
"Status": "PENDING",
"SubmittedAt": "2026-06-15T10:04:11.000Z"
}
}
Latency-based routing — fast multi-Region apps
Latency-based routing returns the record in the AWS Region with the lowest measured network latency to the resolver. If you run the same app in us-east-1 and eu-west-1, a user in Frankfurt is sent to Europe and a user in Virginia to the US.
When to use it: identical stacks deployed in multiple Regions where speed matters. When NOT to use it: single-Region apps, or when law requires geographic routing (use geolocation instead). Each latency record carries a Region field rather than a weight.
aws route53 change-resource-record-sets \
--hosted-zone-id Z0123456789ABCDEFGHIJ \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "app.example.com",
"Type": "A",
"SetIdentifier": "eu-west-1",
"Region": "eu-west-1",
"TTL": 60,
"ResourceRecords": [{ "Value": "198.51.100.20" }]
}
}]
}'
Geolocation and geoproximity
Geolocation routes by where the query comes from — continent, country, or US state. Use it for compliance (“EU users must hit EU servers”) or localized content (language, currency). Always create a Default location record to catch users that match no rule, or those queries return no answer.
Geoproximity routes by physical distance to your resources and adds a bias (-99 to +99) that grows or shrinks a Region’s geographic reach. Use it when you want to shift load between Regions (e.g. send more traffic to a larger data center). It requires Route 53 traffic flow policies.
Failover routing — disaster recovery
Failover routing pairs a primary record with a secondary. Route 53 serves the primary while its associated health check passes; when the health check fails, it serves the secondary. This is the standard active-passive DR pattern: primary in your main Region, secondary pointing at a static “we’ll be right back” page or a warm standby.
aws route53 change-resource-record-sets \
--hosted-zone-id Z0123456789ABCDEFGHIJ \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "app.example.com",
"Type": "A",
"SetIdentifier": "primary",
"Failover": "PRIMARY",
"TTL": 30,
"HealthCheckId": "abcd1234-5678-90ef-ghij-1234567890ab",
"ResourceRecords": [{ "Value": "203.0.113.10" }]
}
}]
}'
Gotcha — failover is not instant. Even after a health check fails, resolvers and browsers keep serving the cached IP until the TTL expires. With a 300-second TTL, users can hit the dead endpoint for up to 5 minutes. Use a low TTL (30-60s) on failover and weighted records, and always attach health checks. Lower TTLs mean more queries (Route 53 charges per million standard queries, roughly $0.40), but for failover the trade is worth it.
Multivalue answer routing
Multivalue answer routing returns up to 8 healthy records in random order, letting the client pick one. It is a cheap way to spread requests and avoid dead endpoints, but it is not a load balancer — there’s no traffic-aware distribution, just randomized DNS answers with health checks. Use it for simple fault tolerance; use an Application/Network Load Balancer when you need real load balancing.
Best Practices
- Keep TTLs low (30-60s) on failover, weighted, and latency records so changes propagate quickly.
- Always attach Route 53 health checks to failover and multivalue records, and add a
Defaultrecord to geolocation sets. - Treat weighted ratios as approximate across resolvers, not exact per-user splits — verify with real metrics, not the weights alone.
- Use latency-based routing for speed and geolocation for compliance; don’t confuse the two.
- Start blue/green rollouts at a small weight (e.g. 5%), watch CloudWatch metrics, then ramp.
- Use alias records (free, no query charge) to point at AWS resources like ALBs and CloudFront instead of hardcoded IPs where possible.