Route 53’s active-passive failover is less about making your application highly available and more about making your DNS record highly available to point to a healthy endpoint.

Let’s say you’ve got a critical web application running across two regions. You’ve configured Route 53 health checks for both endpoints.

{
  "Comment": "Active-Passive failover for my-app.example.com",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "my-app.example.com.",
        "Type": "A",
        "SetIdentifier": "primary-us-east-1",
        "Failover": "PRIMARY",
        "AliasTarget": {
          "HostedZoneId": "Z1ABCDEFG12345",
          "DNSName": "dualstack.my-app-elb.us-east-1.amazonaws.com.",
          "EvaluateTargetHealth": true
        }
      }
    },
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "my-app.example.com.",
        "Type": "A",
        "SetIdentifier": "secondary-us-west-2",
        "Failover": "SECONDARY",
        "AliasTarget": {
          "HostedZoneId": "Z67890HIJKLMN",
          "DNSName": "dualstack.my-app-elb.us-west-2.amazonaws.com.",
          "EvaluateTargetHealth": true
        }
      }
    },
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "my-app.example.com.us-east-1.route53.amazonaws.com",
        "Type": "A",
        "TTL": 60,
        "ResourceRecords": [
          { "Value": "192.0.2.1" }
        ]
      }
    },
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "my-app.example.com.us-west-2.route53.amazonaws.com",
        "Type": "A",
        "TTL": 60,
        "ResourceRecords": [
          { "Value": "198.51.100.1" }
        ]
      }
    }
  ]
}

Here, my-app.example.com is your primary domain. You have two A records, one designated PRIMARY and the other SECONDARY. Both are Alias records pointing to the ELBs in us-east-1 and us-west-2 respectively. Crucially, EvaluateTargetHealth is set to true on both, meaning Route 53 will consult the health of the target (the ELB, and by extension, your application instances behind it) when deciding which record to return.

The SetIdentifier is what Route 53 uses to associate the PRIMARY and SECONDARY records. The health check associated with the PRIMARY record is what determines its availability. If that health check fails, Route 53 stops returning the PRIMARY record and starts returning the SECONDARY record. The SECONDARY record is only returned if the PRIMARY is unhealthy. The PRIMARY record is always returned if it’s healthy, regardless of the SECONDARY’s health.

This setup is about redirecting traffic at the DNS layer. Route 53’s health checks are typically HTTP/HTTPS checks to a specific endpoint or TCP checks to a port. When you set EvaluateTargetHealth: true on an Alias record pointing to an ELB, Route 53 queries the ELB’s health status. If the ELB reports that its target group is healthy (meaning at least one instance is passing health checks), Route 53 considers the Alias record healthy.

When the PRIMARY record’s associated health check fails (e.g., the ELB in us-east-1 is unhealthy), Route 53 will then check the SECONDARY record. If the SECONDARY record is healthy, Route 53 will start returning the IP address for the us-west-2 ELB. This switch happens quickly, often within seconds of the health check failing, depending on your health check configuration and Route 53’s DNS propagation.

The most surprising thing about this setup is that Route 53 doesn’t actually know if your application is running; it only knows if the endpoint it’s configured to check is responding. If your application crashes but the web server (e.g., Nginx) is still running and responding with a 200 OK, Route 53 will think everything is fine.

Consider this scenario: Your us-east-1 ELB is healthy, and Route 53 returns the us-east-1 IP. A user makes a request. The request hits the us-east-1 ELB. Inside that region, your application instances are running, but a background process that your application depends on has crashed. The web server is still serving cached content or a generic "service unavailable" page, but your core business logic isn’t executing. Route 53, looking only at the ELB’s health, has no visibility into this deeper application failure.

This means your health check needs to be sophisticated enough to test actual application functionality. For example, instead of just checking for a 200 OK on /, your health check might need to query an API endpoint like /healthz that performs a quick database lookup or checks a critical external dependency.

The true power of Route 53 active-passive failover, often overlooked, is its ability to leverage existing health checks. If you already have detailed health checks configured for your ELBs or EC2 instances, you can simply point Route 53’s failover records to those same health checks. This avoids duplicating health monitoring logic. You’re essentially using Route 53 as a DNS-level traffic director based on the health signals already being generated by your infrastructure.

The next step after mastering DNS-based failover is understanding how to manage state and data consistency across regions during a failover event, which often involves strategies like multi-region database replication.

Want structured learning?

Take the full Route53 course →