Tools: Your Dev Database Has Multi-AZ Enabled (You're Paying Double for No Reason) πŸ’Έ

Tools: Your Dev Database Has Multi-AZ Enabled (You're Paying Double for No Reason) πŸ’Έ

Source: Dev.to

RDS Multi-AZ doubles your database costs for high availability. Perfect for production, wasteful for dev/staging. Here's how to disable it with Terraform and save 50%. ## πŸ’Έ The Multi-AZ Tax ## 🎯 When to Keep Multi-AZ ## πŸ› οΈ Terraform Implementation ## Disable Multi-AZ (Single Change) ## Smart Multi-AZ by Environment ## Production Module with Environment Logic ## πŸ“Š Real-World Savings ## Typical Startup (3 environments) ## Scale: 10 Non-Prod Databases ## πŸ’‘ Pro Tips ## 1. Audit All Your Databases ## 2. Use Snapshots for Recovery ## 3. Monitor Downtime (If You Care) ## 4. Test Your Disaster Recovery ## ⚠️ What You Lose (Be Honest) ## 🎯 Quick Decision Matrix ## πŸš€ Quick Start ## 🎯 Summary Quick audit: Check your non-production RDS databases right now. How many have Multi-AZ enabled? If the answer is "all of them," you're literally paying double for databases that don't need high availability. Let me show you how to fix this with one line of Terraform. What Multi-AZ gives you: Perfect for: Production databases serving customers Wasteful for: Dev, staging, QA, demo, test environments Don't use Multi-AZ when: Before (all Multi-AZ): After (Production Multi-AZ only): Single-AZ doesn't mean no backups: Recovery from snapshot takes 5-10 minutes β€” acceptable for dev/staging. For Single-AZ, you'll see downtime during maintenance windows. Plan accordingly. Proves you can recover even without Multi-AZ. Without Multi-AZ, you lose: For production: Keep Multi-AZ. Worth every penny. For everything else: Single-AZ + backups is plenty. Multi-AZ doubles RDS costs for high availability: Stop paying for high availability in environments that don't need it. Disable Multi-AZ on non-prod and save 50%. πŸš€ Disabled Multi-AZ on non-prod? How much did you save? Share in the comments! πŸ’¬ Follow for more AWS cost optimization with Terraform! ⚑ Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse CODE_BLOCK: Single-AZ RDS (db.t3.medium): $60/month Multi-AZ RDS (db.t3.medium): $120/month For a dev database that: - Can tolerate 5-10 minute downtime - Gets wiped weekly anyway - Nobody uses on weekends Annual waste: $720 per database 😱 Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: Single-AZ RDS (db.t3.medium): $60/month Multi-AZ RDS (db.t3.medium): $120/month For a dev database that: - Can tolerate 5-10 minute downtime - Gets wiped weekly anyway - Nobody uses on weekends Annual waste: $720 per database 😱 CODE_BLOCK: Single-AZ RDS (db.t3.medium): $60/month Multi-AZ RDS (db.t3.medium): $120/month For a dev database that: - Can tolerate 5-10 minute downtime - Gets wiped weekly anyway - Nobody uses on weekends Annual waste: $720 per database 😱 COMMAND_BLOCK: resource "aws_db_instance" "staging" { identifier = "app-staging" engine = "postgres" instance_class = "db.t3.medium" allocated_storage = 100 storage_type = "gp3" multi_az = true # ← Costing you double! backup_retention_period = 7 skip_final_snapshot = true } Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: resource "aws_db_instance" "staging" { identifier = "app-staging" engine = "postgres" instance_class = "db.t3.medium" allocated_storage = 100 storage_type = "gp3" multi_az = true # ← Costing you double! backup_retention_period = 7 skip_final_snapshot = true } COMMAND_BLOCK: resource "aws_db_instance" "staging" { identifier = "app-staging" engine = "postgres" instance_class = "db.t3.medium" allocated_storage = 100 storage_type = "gp3" multi_az = true # ← Costing you double! backup_retention_period = 7 skip_final_snapshot = true } COMMAND_BLOCK: resource "aws_db_instance" "staging" { identifier = "app-staging" engine = "postgres" instance_class = "db.t3.medium" allocated_storage = 100 storage_type = "gp3" multi_az = false # ← Changed! Saves 50% backup_retention_period = 7 skip_final_snapshot = true } Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: resource "aws_db_instance" "staging" { identifier = "app-staging" engine = "postgres" instance_class = "db.t3.medium" allocated_storage = 100 storage_type = "gp3" multi_az = false # ← Changed! Saves 50% backup_retention_period = 7 skip_final_snapshot = true } COMMAND_BLOCK: resource "aws_db_instance" "staging" { identifier = "app-staging" engine = "postgres" instance_class = "db.t3.medium" allocated_storage = 100 storage_type = "gp3" multi_az = false # ← Changed! Saves 50% backup_retention_period = 7 skip_final_snapshot = true } COMMAND_BLOCK: terraform apply # RDS will modify the instance (takes 5-10 minutes) # Removes standby instance # Immediate 50% cost reduction Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: terraform apply # RDS will modify the instance (takes 5-10 minutes) # Removes standby instance # Immediate 50% cost reduction COMMAND_BLOCK: terraform apply # RDS will modify the instance (takes 5-10 minutes) # Removes standby instance # Immediate 50% cost reduction COMMAND_BLOCK: # variables.tf variable "environment" { description = "Environment name" type = string } locals { # Multi-AZ only for production is_production = var.environment == "production" multi_az_config = { production = true staging = false dev = false qa = false } } resource "aws_db_instance" "app" { identifier = "app-${var.environment}" engine = "postgres" instance_class = local.is_production ? "db.r6g.large" : "db.t3.medium" allocated_storage = 100 storage_type = "gp3" # Multi-AZ based on environment multi_az = local.multi_az_config[var.environment] # Production gets longer retention backup_retention_period = local.is_production ? 30 : 7 # Production gets final snapshot skip_final_snapshot = !local.is_production # Production uses encrypted storage storage_encrypted = local.is_production tags = { Environment = var.environment MultiAZ = local.multi_az_config[var.environment] } } Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: # variables.tf variable "environment" { description = "Environment name" type = string } locals { # Multi-AZ only for production is_production = var.environment == "production" multi_az_config = { production = true staging = false dev = false qa = false } } resource "aws_db_instance" "app" { identifier = "app-${var.environment}" engine = "postgres" instance_class = local.is_production ? "db.r6g.large" : "db.t3.medium" allocated_storage = 100 storage_type = "gp3" # Multi-AZ based on environment multi_az = local.multi_az_config[var.environment] # Production gets longer retention backup_retention_period = local.is_production ? 30 : 7 # Production gets final snapshot skip_final_snapshot = !local.is_production # Production uses encrypted storage storage_encrypted = local.is_production tags = { Environment = var.environment MultiAZ = local.multi_az_config[var.environment] } } COMMAND_BLOCK: # variables.tf variable "environment" { description = "Environment name" type = string } locals { # Multi-AZ only for production is_production = var.environment == "production" multi_az_config = { production = true staging = false dev = false qa = false } } resource "aws_db_instance" "app" { identifier = "app-${var.environment}" engine = "postgres" instance_class = local.is_production ? "db.r6g.large" : "db.t3.medium" allocated_storage = 100 storage_type = "gp3" # Multi-AZ based on environment multi_az = local.multi_az_config[var.environment] # Production gets longer retention backup_retention_period = local.is_production ? 30 : 7 # Production gets final snapshot skip_final_snapshot = !local.is_production # Production uses encrypted storage storage_encrypted = local.is_production tags = { Environment = var.environment MultiAZ = local.multi_az_config[var.environment] } } COMMAND_BLOCK: # modules/rds-instance/main.tf variable "name" { description = "Database identifier" type = string } variable "environment" { description = "Environment (production, staging, dev)" type = string validation { condition = contains(["production", "staging", "dev", "qa"], var.environment) error_message = "Environment must be production, staging, dev, or qa." } } variable "engine" { description = "Database engine" type = string default = "postgres" } variable "instance_class" { description = "Instance class" type = string } variable "allocated_storage" { description = "Storage in GB" type = number default = 100 } locals { is_production = var.environment == "production" # Environment-specific settings config = { multi_az = local.is_production backup_retention_period = local.is_production ? 30 : 7 skip_final_snapshot = !local.is_production storage_encrypted = local.is_production deletion_protection = local.is_production } } resource "aws_db_instance" "this" { identifier = "${var.name}-${var.environment}" engine = var.engine instance_class = var.instance_class allocated_storage = var.allocated_storage storage_type = "gp3" # Environment-based configuration multi_az = local.config.multi_az backup_retention_period = local.config.backup_retention_period skip_final_snapshot = local.config.skip_final_snapshot storage_encrypted = local.config.storage_encrypted deletion_protection = local.config.deletion_protection # Always use automated backups backup_window = "03:00-04:00" maintenance_window = "sun:04:00-sun:05:00" tags = { Name = "${var.name}-${var.environment}" Environment = var.environment MultiAZ = local.config.multi_az ManagedBy = "terraform" } } output "endpoint" { value = aws_db_instance.this.endpoint } output "multi_az_enabled" { value = aws_db_instance.this.multi_az } Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: # modules/rds-instance/main.tf variable "name" { description = "Database identifier" type = string } variable "environment" { description = "Environment (production, staging, dev)" type = string validation { condition = contains(["production", "staging", "dev", "qa"], var.environment) error_message = "Environment must be production, staging, dev, or qa." } } variable "engine" { description = "Database engine" type = string default = "postgres" } variable "instance_class" { description = "Instance class" type = string } variable "allocated_storage" { description = "Storage in GB" type = number default = 100 } locals { is_production = var.environment == "production" # Environment-specific settings config = { multi_az = local.is_production backup_retention_period = local.is_production ? 30 : 7 skip_final_snapshot = !local.is_production storage_encrypted = local.is_production deletion_protection = local.is_production } } resource "aws_db_instance" "this" { identifier = "${var.name}-${var.environment}" engine = var.engine instance_class = var.instance_class allocated_storage = var.allocated_storage storage_type = "gp3" # Environment-based configuration multi_az = local.config.multi_az backup_retention_period = local.config.backup_retention_period skip_final_snapshot = local.config.skip_final_snapshot storage_encrypted = local.config.storage_encrypted deletion_protection = local.config.deletion_protection # Always use automated backups backup_window = "03:00-04:00" maintenance_window = "sun:04:00-sun:05:00" tags = { Name = "${var.name}-${var.environment}" Environment = var.environment MultiAZ = local.config.multi_az ManagedBy = "terraform" } } output "endpoint" { value = aws_db_instance.this.endpoint } output "multi_az_enabled" { value = aws_db_instance.this.multi_az } COMMAND_BLOCK: # modules/rds-instance/main.tf variable "name" { description = "Database identifier" type = string } variable "environment" { description = "Environment (production, staging, dev)" type = string validation { condition = contains(["production", "staging", "dev", "qa"], var.environment) error_message = "Environment must be production, staging, dev, or qa." } } variable "engine" { description = "Database engine" type = string default = "postgres" } variable "instance_class" { description = "Instance class" type = string } variable "allocated_storage" { description = "Storage in GB" type = number default = 100 } locals { is_production = var.environment == "production" # Environment-specific settings config = { multi_az = local.is_production backup_retention_period = local.is_production ? 30 : 7 skip_final_snapshot = !local.is_production storage_encrypted = local.is_production deletion_protection = local.is_production } } resource "aws_db_instance" "this" { identifier = "${var.name}-${var.environment}" engine = var.engine instance_class = var.instance_class allocated_storage = var.allocated_storage storage_type = "gp3" # Environment-based configuration multi_az = local.config.multi_az backup_retention_period = local.config.backup_retention_period skip_final_snapshot = local.config.skip_final_snapshot storage_encrypted = local.config.storage_encrypted deletion_protection = local.config.deletion_protection # Always use automated backups backup_window = "03:00-04:00" maintenance_window = "sun:04:00-sun:05:00" tags = { Name = "${var.name}-${var.environment}" Environment = var.environment MultiAZ = local.config.multi_az ManagedBy = "terraform" } } output "endpoint" { value = aws_db_instance.this.endpoint } output "multi_az_enabled" { value = aws_db_instance.this.multi_az } COMMAND_BLOCK: # Production - Multi-AZ enabled module "db_production" { source = "./modules/rds-instance" name = "myapp" environment = "production" instance_class = "db.r6g.large" allocated_storage = 500 } # Staging - Single-AZ module "db_staging" { source = "./modules/rds-instance" name = "myapp" environment = "staging" instance_class = "db.t3.medium" allocated_storage = 100 } # Dev - Single-AZ module "db_dev" { source = "./modules/rds-instance" name = "myapp" environment = "dev" instance_class = "db.t3.small" allocated_storage = 50 } output "databases" { value = { production = { endpoint = module.db_production.endpoint multi_az = module.db_production.multi_az_enabled } staging = { endpoint = module.db_staging.endpoint multi_az = module.db_staging.multi_az_enabled } dev = { endpoint = module.db_dev.endpoint multi_az = module.db_dev.multi_az_enabled } } } Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: # Production - Multi-AZ enabled module "db_production" { source = "./modules/rds-instance" name = "myapp" environment = "production" instance_class = "db.r6g.large" allocated_storage = 500 } # Staging - Single-AZ module "db_staging" { source = "./modules/rds-instance" name = "myapp" environment = "staging" instance_class = "db.t3.medium" allocated_storage = 100 } # Dev - Single-AZ module "db_dev" { source = "./modules/rds-instance" name = "myapp" environment = "dev" instance_class = "db.t3.small" allocated_storage = 50 } output "databases" { value = { production = { endpoint = module.db_production.endpoint multi_az = module.db_production.multi_az_enabled } staging = { endpoint = module.db_staging.endpoint multi_az = module.db_staging.multi_az_enabled } dev = { endpoint = module.db_dev.endpoint multi_az = module.db_dev.multi_az_enabled } } } COMMAND_BLOCK: # Production - Multi-AZ enabled module "db_production" { source = "./modules/rds-instance" name = "myapp" environment = "production" instance_class = "db.r6g.large" allocated_storage = 500 } # Staging - Single-AZ module "db_staging" { source = "./modules/rds-instance" name = "myapp" environment = "staging" instance_class = "db.t3.medium" allocated_storage = 100 } # Dev - Single-AZ module "db_dev" { source = "./modules/rds-instance" name = "myapp" environment = "dev" instance_class = "db.t3.small" allocated_storage = 50 } output "databases" { value = { production = { endpoint = module.db_production.endpoint multi_az = module.db_production.multi_az_enabled } staging = { endpoint = module.db_staging.endpoint multi_az = module.db_staging.multi_az_enabled } dev = { endpoint = module.db_dev.endpoint multi_az = module.db_dev.multi_az_enabled } } } CODE_BLOCK: Production: db.r6g.large Multi-AZ = $350/month Staging: db.t3.large Multi-AZ = $120/month Dev: db.t3.medium Multi-AZ = $120/month Total: $590/month Annual: $7,080 Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: Production: db.r6g.large Multi-AZ = $350/month Staging: db.t3.large Multi-AZ = $120/month Dev: db.t3.medium Multi-AZ = $120/month Total: $590/month Annual: $7,080 CODE_BLOCK: Production: db.r6g.large Multi-AZ = $350/month Staging: db.t3.large Multi-AZ = $120/month Dev: db.t3.medium Multi-AZ = $120/month Total: $590/month Annual: $7,080 CODE_BLOCK: Production: db.r6g.large Multi-AZ = $350/month (kept) Staging: db.t3.large Single-AZ = $60/month (saved 50%) Dev: db.t3.medium Single-AZ = $60/month (saved 50%) Total: $470/month Annual: $5,640 Savings: $120/month = $1,440/year (20% reduction!) πŸŽ‰ Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: Production: db.r6g.large Multi-AZ = $350/month (kept) Staging: db.t3.large Single-AZ = $60/month (saved 50%) Dev: db.t3.medium Single-AZ = $60/month (saved 50%) Total: $470/month Annual: $5,640 Savings: $120/month = $1,440/year (20% reduction!) πŸŽ‰ CODE_BLOCK: Production: db.r6g.large Multi-AZ = $350/month (kept) Staging: db.t3.large Single-AZ = $60/month (saved 50%) Dev: db.t3.medium Single-AZ = $60/month (saved 50%) Total: $470/month Annual: $5,640 Savings: $120/month = $1,440/year (20% reduction!) πŸŽ‰ CODE_BLOCK: 10 Γ— db.t3.medium Multi-AZ = $1,200/month Switch to Single-AZ: 10 Γ— db.t3.medium Single-AZ = $600/month Savings: $600/month = $7,200/year (50% reduction!) πŸ’° Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: 10 Γ— db.t3.medium Multi-AZ = $1,200/month Switch to Single-AZ: 10 Γ— db.t3.medium Single-AZ = $600/month Savings: $600/month = $7,200/year (50% reduction!) πŸ’° CODE_BLOCK: 10 Γ— db.t3.medium Multi-AZ = $1,200/month Switch to Single-AZ: 10 Γ— db.t3.medium Single-AZ = $600/month Savings: $600/month = $7,200/year (50% reduction!) πŸ’° COMMAND_BLOCK: # List all RDS instances with Multi-AZ status aws rds describe-db-instances \ --query 'DBInstances[*].[DBInstanceIdentifier,MultiAZ,DBInstanceClass]' \ --output table # Filter only Multi-AZ non-prod aws rds describe-db-instances \ --query 'DBInstances[?MultiAZ==`true`].[DBInstanceIdentifier]' \ --output text | grep -E '(dev|staging|qa|test)' Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: # List all RDS instances with Multi-AZ status aws rds describe-db-instances \ --query 'DBInstances[*].[DBInstanceIdentifier,MultiAZ,DBInstanceClass]' \ --output table # Filter only Multi-AZ non-prod aws rds describe-db-instances \ --query 'DBInstances[?MultiAZ==`true`].[DBInstanceIdentifier]' \ --output text | grep -E '(dev|staging|qa|test)' COMMAND_BLOCK: # List all RDS instances with Multi-AZ status aws rds describe-db-instances \ --query 'DBInstances[*].[DBInstanceIdentifier,MultiAZ,DBInstanceClass]' \ --output table # Filter only Multi-AZ non-prod aws rds describe-db-instances \ --query 'DBInstances[?MultiAZ==`true`].[DBInstanceIdentifier]' \ --output text | grep -E '(dev|staging|qa|test)' COMMAND_BLOCK: resource "aws_db_instance" "dev" { # ... other config ... multi_az = false # Single-AZ # Still have automated backups! backup_retention_period = 7 backup_window = "03:00-04:00" # Can restore from snapshot if needed } Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: resource "aws_db_instance" "dev" { # ... other config ... multi_az = false # Single-AZ # Still have automated backups! backup_retention_period = 7 backup_window = "03:00-04:00" # Can restore from snapshot if needed } COMMAND_BLOCK: resource "aws_db_instance" "dev" { # ... other config ... multi_az = false # Single-AZ # Still have automated backups! backup_retention_period = 7 backup_window = "03:00-04:00" # Can restore from snapshot if needed } CODE_BLOCK: resource "aws_cloudwatch_metric_alarm" "db_down" { alarm_name = "${var.name}-database-down" comparison_operator = "LessThanThreshold" evaluation_periods = 1 metric_name = "DatabaseConnections" namespace = "AWS/RDS" period = 60 statistic = "Average" threshold = 1 alarm_description = "Database has no connections" dimensions = { DBInstanceIdentifier = aws_db_instance.dev.id } } Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: resource "aws_cloudwatch_metric_alarm" "db_down" { alarm_name = "${var.name}-database-down" comparison_operator = "LessThanThreshold" evaluation_periods = 1 metric_name = "DatabaseConnections" namespace = "AWS/RDS" period = 60 statistic = "Average" threshold = 1 alarm_description = "Database has no connections" dimensions = { DBInstanceIdentifier = aws_db_instance.dev.id } } CODE_BLOCK: resource "aws_cloudwatch_metric_alarm" "db_down" { alarm_name = "${var.name}-database-down" comparison_operator = "LessThanThreshold" evaluation_periods = 1 metric_name = "DatabaseConnections" namespace = "AWS/RDS" period = 60 statistic = "Average" threshold = 1 alarm_description = "Database has no connections" dimensions = { DBInstanceIdentifier = aws_db_instance.dev.id } } COMMAND_BLOCK: # Create manual snapshot aws rds create-db-snapshot \ --db-instance-identifier app-dev \ --db-snapshot-identifier app-dev-manual-snapshot # Restore from snapshot (test recovery) aws rds restore-db-instance-from-db-snapshot \ --db-instance-identifier app-dev-restored \ --db-snapshot-identifier app-dev-manual-snapshot Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: # Create manual snapshot aws rds create-db-snapshot \ --db-instance-identifier app-dev \ --db-snapshot-identifier app-dev-manual-snapshot # Restore from snapshot (test recovery) aws rds restore-db-instance-from-db-snapshot \ --db-instance-identifier app-dev-restored \ --db-snapshot-identifier app-dev-manual-snapshot COMMAND_BLOCK: # Create manual snapshot aws rds create-db-snapshot \ --db-instance-identifier app-dev \ --db-snapshot-identifier app-dev-manual-snapshot # Restore from snapshot (test recovery) aws rds restore-db-instance-from-db-snapshot \ --db-instance-identifier app-dev-restored \ --db-snapshot-identifier app-dev-manual-snapshot COMMAND_BLOCK: # 1. Audit current Multi-AZ usage aws rds describe-db-instances \ --query 'DBInstances[?MultiAZ==`true`].[DBInstanceIdentifier,DBInstanceClass,MultiAZ]' \ --output table # 2. Identify non-production databases # (anything with dev, staging, qa, test in name) # 3. Update Terraform # Change: multi_az = true β†’ multi_az = false # 4. Apply changes terraform apply # 5. Watch your bill drop next month πŸ’° Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: # 1. Audit current Multi-AZ usage aws rds describe-db-instances \ --query 'DBInstances[?MultiAZ==`true`].[DBInstanceIdentifier,DBInstanceClass,MultiAZ]' \ --output table # 2. Identify non-production databases # (anything with dev, staging, qa, test in name) # 3. Update Terraform # Change: multi_az = true β†’ multi_az = false # 4. Apply changes terraform apply # 5. Watch your bill drop next month πŸ’° COMMAND_BLOCK: # 1. Audit current Multi-AZ usage aws rds describe-db-instances \ --query 'DBInstances[?MultiAZ==`true`].[DBInstanceIdentifier,DBInstanceClass,MultiAZ]' \ --output table # 2. Identify non-production databases # (anything with dev, staging, qa, test in name) # 3. Update Terraform # Change: multi_az = true β†’ multi_az = false # 4. Apply changes terraform apply # 5. Watch your bill drop next month πŸ’° - Automatic failover to standby instance (~60-120 seconds) - Synchronous replication to standby - No data loss during failure - 99.95% availability SLA - Exactly 2x the instance price (you pay for standby too) - Exactly 2x the storage (replicated) - 2x backup storage (from both instances) - βœ… Production database - βœ… Customer-facing application - βœ… Revenue-generating service - βœ… SLA requires < 2 min failover - βœ… Zero tolerance for data loss - ❌ Development environment - ❌ Staging/QA environment - ❌ Personal projects - ❌ Internal tools - ❌ Test databases - ❌ 5-10 min downtime is acceptable - ❌ Automatic failover (manual recovery needed) - ❌ Synchronous replication (use backups instead) - ❌ 99.95% SLA (becomes 99.5% single-AZ) - ❌ Zero RPO during failure (some data loss possible) - βœ… 50% cost reduction - βœ… Still have automated backups - βœ… Can restore from snapshot in 5-10 min - βœ… Good enough for non-production - Production: Worth it - Non-production: Wasteful - One line in Terraform: multi_az = false - 50% instant savings on non-prod databases - Still get automated backups - Recovery time: 5-10 minutes (acceptable) - 3 non-prod databases: $1,440/year - 10 non-prod databases: $7,200/year