Routing can skip what is broken only if something checks. A Route 53 health check requests a URL from checkers in several regions, every 30 seconds (10 costs more). A 2xx or 3xx answer passes. After FailureThreshold failures in a row the check turns unhealthy; the same number of passes turns it healthy again.
A check on the load balancer
With the load balancer's DNS name in DNS (DNS=$(aws elbv2 describe-load-balancers --names market-alb --query "LoadBalancers[0].DNSName" --output text)):
HC=$(aws route53 create-health-check --caller-reference shop-alb-1 --health-check-config Type=HTTP,FullyQualifiedDomainName=$DNS,Port=80,ResourcePath=/,RequestInterval=10,FailureThreshold=2 --query HealthCheck.Id --output text)Name the check so you can tell it apart:
aws route53 change-tags-for-resource --resource-type healthcheck --resource-id $HC --add-tags Key=Name,Value=shop-albaws route53 get-health-check-status --health-check-id $HC --query "HealthCheckObservations[].[Region,StatusReport.Status]" --output tableEach checker reports what it saw: Success: HTTP Status Code 200, OK, or the failure, such as HTTP Status Code 404 for a path that does not exist. aws route53 update-health-check --health-check-id $HC --resource-path /health changes what it requests (also --port, --failure-threshold; the interval is fixed). aws route53 list-health-checks --query "HealthChecks[].[Id,HealthCheckConfig.FullyQualifiedDomainName]" --output table lists them all.
A failover pair
Two sets of one name: PRIMARY with the health check, SECONDARY for when it fails. Here the secondary is a "back soon" page in a website bucket named shop.monstermarket.example (an S3 alias needs the bucket named like the record), which shares nothing with the servers. Fill in HC-ID and LB-DNS with $HC and $DNS, and save as failover.json:
{ "Changes": [
{ "Action": "UPSERT", "ResourceRecordSet": { "Name": "shop.monstermarket.example",
"Type": "A", "SetIdentifier": "main", "Failover": "PRIMARY", "HealthCheckId": "HC-ID",
"AliasTarget": { "HostedZoneId": "Z35SXDOTRQ7X7K", "DNSName": "LB-DNS",
"EvaluateTargetHealth": false } } },
{ "Action": "UPSERT", "ResourceRecordSet": { "Name": "shop.monstermarket.example",
"Type": "A", "SetIdentifier": "backup", "Failover": "SECONDARY",
"AliasTarget": { "HostedZoneId": "Z3AQBSTGFYJSTF",
"DNSName": "s3-website-us-east-1.amazonaws.com", "EvaluateTargetHealth": false } } } ] }aws route53 change-resource-record-sets --hosted-zone-id $ZONE --change-batch file://failover.jsonRoute 53 answers with the primary while it is healthy and the secondary when it is not. If both are unhealthy, the primary. An alias to a load balancer with EvaluateTargetHealth on works without a health check, judged by the targets; a health check tests the URL itself, so it also catches a broken page that the targets' own checks pass.
Checkers come from the internet, so they cannot reach a private address: for that, a health check watches a CloudWatch alarm instead. A calculated check combines others ("healthy while two of three are"). Each check costs $0.50 a month.