This project builds the highest level of cloud availability — an active-active multi-region architecture where your application runs simultaneously in two AWS regions. Users in India get served from Mumbai (ap-south-1). Users in Southeast Asia get served from Singapore (ap-southeast-1). If Mumbai goes down completely, all traffic automatically shifts to Singapore within 60 seconds — no manual intervention, no hotline calls at 3am. This is how Hotstar serves cricket streaming to 50 million concurrent viewers during IPL — no single region failure can take down the platform because both regions are always actively serving traffic. Indian Users SE Asian Users | | v v Route53 (Global DNS with latency routing) | | +----------------+ +------------------+ | Mumbai | | Singapore | | ap-south-1 | | ap-southeast-1 | | | | | | ALB | | ALB | | EC2 ASG | | EC2 ASG | | RDS Primary |--->| RDS Read Replica | | (read/write) | | (read, promoted | | | | if Mumbai fails) | +----------------+ +------------------+ | | +----------+-----------+ | RDS Global Database (replication lag < 1 second)
A single-region application has a single point of failure. AWS regions do have outages — ap-south-1 has had incidents that affected multiple availability zones simultaneously. When that happens to a single-region application, it goes completely offline until AWS resolves the incident — sometimes for hours. With multi-region active-active, a regional failure means your application loses capacity but stays online. Route53 health checks detect the failing region within 30 seconds and stop routing traffic there. Singapore continues serving all users within 60 seconds of the Mumbai failure beginning.
### Step 1: Set Up Terraform Workspaces for Multi-Region ```bash mkdir multi-region-app && cd multi-region-app ## Terraform workspaces let you use the same code for multiple environments ## Here we use them for different regions terraform workspace new mumbai terraform workspace new singapore terraform workspace list ## Expected: mumbai, singapore ## Switch to mumbai workspace terraform workspace select mumbai ``` Create `variables.tf`: ```hcl variable "region_config" { type = map(object({ region = string az_suffixes = list(string) is_primary = bool })) default = { mumbai = { region = "ap-south-1" az_suffixes = ["a", "b"] is_primary = true # Mumbai hosts the RDS primary } singapore = { region = "ap-southeast-1" az_suffixes = ["a", "b"] is_primary = false # Singapore has the read replica } } } locals { # Automatically use the right config based on the workspace config = var.region_config[terraform.workspace] } ``` Create `main.tf`: ```hcl provider "aws" { region = local.config.region } ## The same VPC, ASG, and ALB code runs in both workspaces ## Only the region and is_primary flag differ resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" enable_dns_hostnames = true tags = { Name = "${terraform.workspace}-vpc" Region = local.config.region } } resource "aws_subnet" "public" { count = length(local.config.az_suffixes) vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index) availability_zone = "${local.config.region}${local.config.az_suffixes[count.index]}" map_public_ip_on_launch = true tags = { Name = "${terraform.workspace}-public-${count.index}" } } resource "aws_autoscaling_group" "app" { name = "${terraform.workspace}-app-asg" vpc_zone_identifier = aws_subnet.public[*].id target_group_arns = [aws_lb_target_group.app.arn] health_check_type = "ELB" min_size = 2 max_size = 10 desired_capacity = 2 launch_template { id = aws_launch_template.app.id version = "$Latest" } tag { key = "Name" value = "${terraform.workspace}-app-instance" propagate_at_launch = true } } ``` ### Step 2: Set Up RDS Global Database ```hcl ## This runs only in the mumbai workspace (primary region) ## The Singapore workspace gets a read replica automatically through Global Database resource "aws_rds_global_cluster" "main" { count = local.config.is_primary ? 1 : 0 # Only create in primary workspace global_cluster_identifier = "production-global-db" engine = "aurora-postgresql" engine_version = "15.2" database_name = "appdb" storage_encrypted = true } resource "aws_rds_cluster" "app" { cluster_identifier = "${terraform.workspace}-aurora-cluster" engine = "aurora-postgresql" engine_version = "15.2" database_name = local.config.is_primary ? "appdb" : null master_username = local.config.is_primary ? "postgres" : null master_password = local.config.is_primary ? var.db_password : null # Link to global cluster global_cluster_identifier = local.config.is_primary ? aws_rds_global_cluster.main[0].id : var.global_cluster_id db_subnet_group_name = aws_db_subnet_group.main.name vpc_security_group_ids = [aws_security_group.rds.id] # Automatic backups backup_retention_period = 7 preferred_backup_window = "02:00-03:00" deletion_protection = true skip_final_snapshot = false tags = { Role = local.config.is_primary ? "primary" : "replica" Region = local.config.region } } resource "aws_rds_cluster_instance" "app" { count = 2 # 2 instances per region cluster_identifier = aws_rds_cluster.app.id instance_class = "db.r6g.large" engine = aws_rds_cluster.app.engine engine_version = aws_rds_cluster.app.engine_version performance_insights_enabled = true monitoring_interval = 60 } ``` ### Step 3: Configure Route53 with Latency Routing and Health Checks ```hcl ## Route53 is global — this runs once, not per workspace ## Put this in a separate route53 directory provider "aws" { region = "us-east-1" # Route53 is global but API is in us-east-1 alias = "global" } ## Health check for Mumbai ALB resource "aws_route53_health_check" "mumbai" { provider = aws.global fqdn = var.mumbai_alb_dns port = 80 type = "HTTP" resource_path = "/health" failure_threshold = 3 # 3 consecutive failures = unhealthy request_interval = 10 # Check every 10 seconds (fastest possible) tags = { Name = "mumbai-health-check" } } ## Health check for Singapore ALB resource "aws_route53_health_check" "singapore" { provider = aws.global fqdn = var.singapore_alb_dns port = 80 type = "HTTP" resource_path = "/health" failure_threshold = 3 request_interval = 10 tags = { Name = "singapore-health-check" } } ## Latency-based routing — users go to the nearest region resource "aws_route53_record" "mumbai" { provider = aws.global zone_id = var.hosted_zone_id name = "api.devopsnetwork.in" type = "CNAME" latency_routing_policy { region = "ap-south-1" } set_identifier = "mumbai" health_check_id = aws_route53_health_check.mumbai.id ttl = 30 # Low TTL = faster failover records = [var.mumbai_alb_dns] } resource "aws_route53_record" "singapore" { provider = aws.global zone_id = var.hosted_zone_id name = "api.devopsnetwork.in" type = "CNAME" latency_routing_policy { region = "ap-southeast-1" } set_identifier = "singapore" health_check_id = aws_route53_health_check.singapore.id ttl = 30 records = [var.singapore_alb_dns] } ``` ### Step 4: Implement Failover — Promote Singapore Replica ```bash ## This procedure runs when Mumbai has a major outage ## Document this BEFORE the outage — not during it ## Step 1: Verify Mumbai is actually failing (not a false alarm) aws route53 get-health-check-status \ --health-check-id MUMBAI_HEALTH_CHECK_ID ## Expected during outage: HealthCheckObservations show failure ## Step 2: Promote Singapore read replica to standalone primary ## This takes 1-2 minutes for Aurora Global Database aws rds failover-global-cluster \ --global-cluster-identifier production-global-db \ --target-db-cluster-identifier singapore-aurora-cluster ## Watch the failover progress aws rds describe-global-clusters \ --global-cluster-identifier production-global-db \ --query 'GlobalClusters[0].GlobalClusterMembers[*].[DBClusterArn,IsWriter]' ## Expected: singapore-aurora-cluster shows IsWriter=true after 1-2 minutes ## Step 3: Update application config to point to Singapore primary ## If using a CNAME for the DB endpoint, update it: aws route53 change-resource-record-sets \ --hosted-zone-id YOUR_ZONE_ID \ --change-batch '{ "Changes": [{ "Action": "UPSERT", "ResourceRecordSet": { "Name": "db.devopsnetwork.in", "Type": "CNAME", "TTL": 60, "ResourceRecords": [{"Value": "SINGAPORE_CLUSTER_ENDPOINT"}] } }] }' ## Step 4: Verify Singapore is serving all traffic curl https://api.devopsnetwork.in/health ## Expected: 200 response from Singapore region ```
```bash ## 1. Verify infrastructure in both regions terraform workspace select mumbai && terraform output terraform workspace select singapore && terraform output ## Expected: Both workspaces show ALB DNS names and ASG names ## 2. Test latency-based routing (from different locations) ## From India — should resolve to Mumbai dig api.devopsnetwork.in ## From Singapore — should resolve to Singapore ## Use an online DNS propagation checker like dnschecker.org ## 3. Test health check failover ## Temporarily stop the Mumbai ALB listener aws elbv2 modify-listener \ --listener-arn MUMBAI_LISTENER_ARN \ --default-actions '[{"Type":"fixed-response","FixedResponseConfig":{"StatusCode":"503"}}]' ## Wait 30-60 seconds for Route53 to detect the failure ## Run this in a loop and watch when it switches: for i in {1..30}; do REGION=$(curl -s https://api.devopsnetwork.in/region) echo "$(date): Serving from $REGION" sleep 5 done ## Expected: After ~30-60 seconds, all requests show Singapore ## 4. Verify RDS replication lag aws cloudwatch get-metric-statistics \ --namespace AWS/RDS \ --metric-name AuroraGlobalDBReplicationLag \ --dimensions Name=DBClusterIdentifier,Value=singapore-aurora-cluster \ --start-time $(date -u -d '-1 hour' '+%Y-%m-%dT%H:%M:%SZ') \ --end-time $(date -u '+%Y-%m-%dT%H:%M:%SZ') \ --period 300 \ --statistics Average \ --region ap-southeast-1 ## Expected: AuroraGlobalDBReplicationLag < 1000ms (1 second) ## 5. Run a full failover drill ## Time the entire failover from Mumbai failure detection to Singapore serving all traffic ## Document the actual RTO (Recovery Time Objective) measured echo "Multi-region active-active architecture validated" ```
This project builds the highest level of cloud availability — an active-active multi-region architecture where your appl...
A single-region application has a single point of failure. AWS regions do have outages — ap-south-1 has had incidents th...
Step 1: Set Up Terraform Workspaces for Multi-Region Create variables.tf: Create main.tf: Step 2: Set Up RDS Global Data...
...
Aligns directly with DevOps, Site Reliability (SRE), and Platform Engineering job descriptions.