Skip to content

Route 53 routing policies decoded: weighted, latency, geolocation, failover

Route 53 has seven routing policies and most teams need two. Here is what weighted, latency, geolocation, and failover routing actually do, and how to pick without overbuilding.

Route 53 offers simple, weighted, latency, failover, geolocation, geoproximity, multivalue answer, and IP-based routing — and the honest guidance is that most production workloads need exactly two of them: simple (or an alias, which behaves like simple) for everything single-target, and one of weighted or failover when a second target appears. Latency and geolocation earn their keep only once you genuinely run the same service in multiple regions. Picking the policy is really picking why two answers exist for one name.

What you are deciding

Every routing policy answers the same question differently: when a resolver asks for app.example.com, which record does Route 53 return?

  • Simple — the one record, always. No health awareness: if the target is down, Route 53 still answers with it.
  • Weighted — you assign each record a weight from 0 to 255 and Route 53 returns each one in proportion. This is the traffic-splitting policy: canary a new stack at 5%, migrate a provider 10% at a time, or park a record at weight 0 to keep it configured but idle. Health checks can be attached so an unhealthy record drops out of the rotation.
  • Latency — Route 53 answers with the record for the region that has the lowest measured network latency from the resolver’s network. Note what it is not: it is not geographic distance and not a promise; it is based on AWS’s latency measurements between networks and regions, and users on a VPN or a distant corporate resolver get the answer that fits the resolver, not the person.
  • Failover — primary while healthy, secondary when not. Covered in depth in the health checks and DNS failover guide.
  • Geolocation — answers based on where the query comes from (continent, country, or US state), with a default record for everyone unmatched. This is the compliance and content-rights policy: EU users to the EU stack, everyone else to the default. Always create the default record — queries from unmatched locations otherwise get no answer at all.
  • Geoproximity — routes based on geographic distance to your resources with a bias dial to shift the boundary. Niche; most teams who reach for it actually wanted latency or geolocation.
  • Multivalue answer — returns up to eight healthy records, letting the client pick. A poor engineer’s load balancer: useful for stateless fleets without an LB, not a replacement for one.
  • IP-based — maps CIDR blocks of the resolver to records. For known-network steering (send this ISP or this office range there). Rare by design.

The real decision has a shape: why does more than one answer exist? If the second target is a standby, that is failover. If it is a percentage experiment or a migration, weighted. If both targets are permanently live in different regions for performance, latency. If law or licensing dictates who goes where, geolocation — because latency routing will happily send a German user to us-east-1 if the path is faster, which is a performance win and a compliance incident.

What to check first

  • How many live targets exist, really? One target means simple/alias, and any fancier policy is configuration debt.
  • Is the split about performance or about rules? Performance says latency; rules say geolocation. They disagree at the margins, and the margins are where the lawyers live.
  • Do the records have health checks? Weighted, latency, and geolocation all support health checks but do not require them — without one, Route 53 keeps answering with a dead target.
  • Is there a default/fallback record? Geolocation without a default silently blackholes unmatched countries.

How to verify

Inspect what exists and what Route 53 would answer:

# See every record and its routing configuration
aws route53 list-resource-record-sets --hosted-zone-id Z0123456789ABC \
  --query "ResourceRecordSets[?Name=='app.example.com.'].[Type,SetIdentifier,Weight,Region,GeoLocation,Failover,HealthCheckId]" \
  --output table

# Ask Route 53 what it would answer for a given resolver location
aws route53 test-dns-answer --hosted-zone-id Z0123456789ABC \
  --record-name app.example.com --record-type A \
  --edns0-client-subnet-ip 203.0.113.0 --edns0-client-subnet-mask 24

The --edns0-client-subnet-ip flag is the underused gem here: it simulates a query from a specific network, which is the only sane way to test geolocation and latency answers without a VPN collection. In the console, each record’s policy shows in Route 53 > Hosted zones > example.com under the Routing policy column; records sharing a name and type must each carry a unique Record ID (set identifier).

The approach

  1. Start with simple or alias and stay there until a second live target exists. Policies are easy to add later; unwinding a speculative geoproximity setup is not.
  2. Use weighted for anything gradual. Canary releases, blue/green cutover at the DNS layer, provider migrations. Shift 5 → 25 → 50 → 100, watching error rates between steps. Weight 0 keeps the old target one edit away from restoration.
  3. Add health checks to every non-simple record. The policies distribute answers; only health checks remove dead ones. A weighted pair without checks fails 50% of your users when one side dies.
  4. Reach for latency only with real multi-region. Two full stacks, replicated data, tested independently. Latency routing on top of a single-region database is a decoration — the cross-region disaster recovery groundwork comes first.
  5. Use geolocation when the requirement is legal, not technical. And write the default record in the same change set as the first country rule, not as a follow-up ticket.
  6. Combine policies with alias chaining when it gets complex. A latency record set can alias to per-region failover pairs — latency picks the region, failover survives within it. Build the tree on paper before building it in the zone.

When this is the wrong move

DNS routing policies steer resolvers, not users, and they steer them slowly. If you need per-request control — sticky sessions, header-based routing, gradual rollout with instant rollback — that belongs at the load balancer or CDN layer, not in DNS. Latency routing is also the wrong instrument for cost steering, since you cannot see or cap which region wins. And multivalue answer is not load balancing: no connection draining, no even distribution guarantee, client-side retry behavior you do not control.

Common mistakes

  • Geolocation without a default record, discovered when a country you never thought about reports the site does not exist.
  • Weighted records without health checks, so the canary keeps receiving its 5% while it burns.
  • Expecting latency routing to respect data residency — it optimizes round-trip time and nothing else.
  • Forgetting that weights are proportions, not percentages: two records at 10 and 30 split 25/75, not 10/30.

Keeping it under control

  • Document, for every name with multiple records, one sentence: why more than one answer exists.
  • Alarm on the health checks backing routed records, not just the endpoints.
  • Test geolocation and latency answers with test-dns-answer and client-subnet simulation after every change.
  • Review the zone quarterly for weight-0 leftovers and set identifiers nobody remembers.

The full policy reference lives in the Route 53 documentation, and it is worth reading once before the architecture meeting rather than during the incident. If nobody on your team truly owns the AWS environment end to end, that is the root of most of these problems — Stack Harbor runs AWS accounts daily under AWS Operations, and you can book an AWS review.