🚦 Mastering AWS Route 53 Failover: Simulating Multi-Region Resilience with EC2 & Nginx

When building production-grade systems, downtime isn’t an if — it’s a when.
A healthy SRE mindset says: design for failure, not against it.
In this post, we’ll simulate a real-world failover scenario using Amazon Route 53, two EC2 instances running Nginx, and a sprinkle of smart routing logic — all without owning a domain.
You’ll see how to make AWS automatically switch traffic between regions when one server goes down. ⚡
🧭 What We’re Building
We’ll set up:
Region 1 (Primary): EC2 with Nginx
Region 2 (Secondary): EC2 with Nginx
Route 53 Failover Routing Policy to automatically switch traffic when Region 1 fails
Both instances host a simple static webpage to make the effect visible.
Here’s the architecture:
+-------------------+
| Route 53 DNS |
| Failover Policy |
+---------+---------+
|
Healthy? ↓ Yes
+-------------------+
| EC2 (Region 1) |
| Nginx: 80 |
+-------------------+
↑ No
|
+-------------------+
| EC2 (Region 2) |
| Nginx: 80 |
+-------------------+
⚙️ Step 1 – Spin Up Two EC2 Instances
Launch two EC2 instances in different regions (e.g., ap-south-1 and us-east-1).
Use Amazon Linux 2 or Ubuntu.
After launch, install Nginx on both:
sudo yum update -y
sudo yum install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
Replace the default index file so you can tell them apart:
echo "This is REGION 1" | sudo tee /usr/share/nginx/html/index.html
And on the second instance:
echo "This is REGION 2" | sudo tee /usr/share/nginx/html/index.html
Make sure Security Groups allow inbound traffic on port 80 (HTTP) from 0.0.0.0/0.
🌐 Step 2 – Create a Hosted Zone (No Custom Domain Needed)
Even without owning a domain, you can create a private hosted zone to simulate DNS routing.
Go to Route 53 → Hosted Zones → Create Hosted Zone
Choose:
Name:
internal.testType: Private hosted zone
VPC association: Select the VPC of your EC2s.
You’ll now have a custom DNS zone like app.internal.test to play with.
🧩 Step 3 – Create Health Checks
We’ll create health checks to monitor both EC2 instances.
Go to Route 53 → Health Checks → Create health check
Choose:
Name:
Primary-EC2-HealthEndpoint type: IP address
IP address: Public IP of EC2 #1
Protocol: HTTP
Port: 80
Path:
/
Repeat for EC2 #2 (secondary region)
Each health check pings the EC2 every 30 seconds to confirm if it’s alive.
💡 Note: Health checks work only with public IPs, since Route 53’s monitoring agents operate from AWS’s public network.
🧭 Step 4 – Configure Failover Routing Policy
Now, let’s wire up the DNS logic.
Inside your Hosted Zone → internal.test → Create Record:
Record 1 – Primary
| Field | Value |
| Record name | app.internal.test |
| Record type | A |
| Value | Public IP of EC2 #1 |
| Routing policy | Failover |
| Failover role | Primary |
| Health check | Primary-EC2-Health |
Record 2 – Secondary
| Field | Value |
| Record name | app.internal.test |
| Record type | A |
| Value | Public IP of EC2 #2 |
| Routing policy | Failover |
| Failover role | Secondary |
| Health check | (Optional or same logic) |
Now both records share the same name, but Route 53 decides which one to serve based on the health checks.
🧪 Step 5 – Test the Failover
On your local system, run:
dig app.internal.test +short
You’ll see the IP of your primary EC2 instance.
Now, stop Nginx on the first EC2:
sudo systemctl stop nginx
Wait ~1–2 minutes (health check interval + DNS TTL), then run:
dig app.internal.test +short
Boom. 🎉
The IP changes to your secondary EC2 instance — your app has officially failed over!
Restart Nginx on EC2 #1, and after a short period, Route 53 will automatically switch back.
📈 What You’ve Achieved
You’ve just built a working active-passive failover system without any external load balancer.
| Layer | Mechanism |
| App | Nginx on EC2 |
| Health | Route 53 HTTP health checks |
| Failover | DNS-level rerouting |
| Recovery | Automatic |
This is exactly how real HA systems begin — the foundation of disaster recovery and SRE-grade design.
💡 Next Steps
You can extend this setup by:
Using Elastic IPs for static endpoints
Integrating CloudWatch alarms for deeper health logic
Automating failback via Lambda or CloudFormation
Later: connecting region-specific databases (like DynamoDB Global Tables)
🧠 TL;DR
Route 53 health checks monitor EC2 health via HTTP.
Failover routing swaps traffic to a healthy region.
Works even without a custom domain (via Private Hosted Zones).
Clean, low-cost intro to disaster recovery thinking in AWS.
💬 “High availability isn’t about uptime — it’s about graceful failure.”
If you found this helpful, give it a 💙 on Hashnode and share it with your DevOps circle.
Next, we’ll explore how to extend this same logic to a multi-region data layer using DynamoDB Global Tables — so the entire stack becomes fault-tolerant end-to-end.



