Skip to content
ExponaBLOG
AWS FOR DEVELOPERS · DAY 084 / 100

Disaster recovery strategies: a AWS guide for developers

Four options, four price points.

Expona Admin10 min read

You've built a solid platform, your customers trust it, and then a database corruption, region outage, or ransomware attack hits. The question isn't if disaster will strike—it's whether your team can recover fast enough to keep the business standing. Disaster recovery strategies aren't about being paranoid; they're about matching your infrastructure decisions to what your business can actually afford to lose.

I've been through this twice: once watching a production database fail at 2 AM with no backup strategy in place, and once implementing a multi-region failover that saved us during a region-wide AWS outage. The difference wasn't heroic debugging—it was having a plan that was actually tested and automated. This article walks you through the four main disaster recovery strategies, from the cheapest option to the fastest, and how to pick the one that fits your reality.

From cheapest to fastest: The four strategies

AWS often frames disaster recovery as a spectrum, and for good reason. Each step up in complexity and speed costs more, but buys you faster recovery and less data loss. You need to understand all four before choosing.

Backup and Restore (RPO: 24 hours, RTO: 12+ hours)

This is the basement option. You take regular snapshots of your RDS database, backups of your S3 buckets, and AMI images of your EC2 instances. When disaster strikes, you restore from the latest backup and bring systems back online.

Real scenario: A small fintech startup I worked with used this for their trading platform. They took daily RDS snapshots, archived logs to S3, and kept infrastructure-as-code templates in GitHub. When their primary database got corrupted, they restored from the previous day's snapshot, replayed transaction logs from S3, and went live in 6 hours. They lost about 12 hours of data, but the business survived.

Cost: Storage for snapshots and backups, maybe $50–200/month depending on data size. One of the cheapest options. The hidden cost is manual work during recovery—you're manually spinning up instances, configuring security groups, and running database restore commands.

When to use it: Non-critical systems, internal tools, sandbox environments, or businesses that can tolerate 12+ hours of downtime.

Pilot Light (RPO: 5–10 minutes, RTO: 2–5 hours)

Imagine keeping a minimal, dormant copy of your infrastructure running in a standby region—but scaled down to near-zero cost. When disaster happens, you activate it, scale it up, and failover your traffic. The pilot light is always on but idle, like a plane on the runway with engines off.

Real scenario: A CRM platform I built kept a second RDS read replica in a different availability zone with automated backups. We also maintained a minimal EC2 instance running a scaled-down version of the API in a second region. When the primary region had infrastructure issues, we promoted the read replica to primary, spun up the full fleet in the standby region, and updated Route 53 DNS weights. The whole process took about 3 hours with manual intervention.

Infrastructure setup:

bash
# In your primary region: regular backups and automated snapshots
aws rds create-db-snapshot \
  --db-instance-identifier prod-db \
  --db-snapshot-identifier prod-db-backup-$(date +%s)

# In your standby region: minimal read replica running
aws rds create-db-instance-read-replica \
  --db-instance-identifier prod-db-standby \
  --source-db-instance-identifier arn:aws:rds:us-east-1:123456789:db:prod-db \
  --db-instance-class db.t3.micro

Cost: The read replica and standby instances run 24/7, so expect $300–600/month extra. Not free, but cheaper than a full standby environment.

When to use it: Business-critical applications where you can tolerate 2–5 hours of downtime and some data loss.

Warm Standby (RPO: 1–5 minutes, RTO: 15–30 minutes)

This is a fully functional, scaled-down replica of your production environment running continuously in a standby region. It's receiving real-time data replication, handling read traffic, or sitting idle but ready to switch. When disaster strikes, you scale it up and switch traffic over in minutes.

Real scenario: A ride-hailing platform I worked on ran warm standby in two regions. The primary region handled all writes; the standby region received replication and was scaled at 30% capacity, handling a portion of read traffic. A multi-master RDS setup kept data synchronized with <5 minute replication lag. When a regional infrastructure failure happened, we scaled up the standby region to 100%, updated the application load balancer targets, and failover completed in 12 minutes. Zero data loss for active ride requests.

Infrastructure code (Terraform):

bash
# Primary RDS with automated backups and Multi-AZ
resource "aws_db_instance" "primary" {
  identifier            = "prod-db-primary"
  engine                = "postgres"
  instance_class        = "db.r5.2xlarge"
  allocated_storage     = 1000
  backup_retention_days = 30
  multi_az              = true
  storage_encrypted     = true
}

# Standby region RDS read replica, scaled down
resource "aws_db_instance" "standby" {
  provider              = aws.standby_region
  identifier            = "prod-db-standby"
  replicate_source_db   = aws_db_instance.primary.identifier
  instance_class        = "db.r5.xlarge"  # 50% of primary
  skip_final_snapshot   = false
  multi_az              = true
}

# Auto Scaling Group in standby region at reduced capacity
resource "aws_autoscaling_group" "standby_asg" {
  provider            = aws.standby_region
  name                = "api-standby-asg"
  desired_capacity    = 2      # vs 8 in primary
  min_size            = 2
  max_size            = 8
  vpc_zone_identifier = var.standby_subnet_ids
  launch_template {
    id      = aws_launch_template.api.id
    version = "$Latest"
  }
}

Cost: $1,500–3,000/month because you're running 30–50% of production capacity continuously. Significant but justified for critical systems.

When to use it: Revenue-critical systems, payment processing, customer-facing platforms. You need RTO under an hour and RPO under 5 minutes.

Multi-site Active-Active (RPO: Real-time, RTO: <5 minutes)

Both regions are live, both handling production traffic, both receiving writes, both serving customers. No failover delay because there's no standby—everything is active. When one region fails, the other keeps running.

Real scenario: A travel booking platform I built for a high-growth startup ran active-active across us-east-1 and eu-west-1. Every booking request was written to both regions using DynamoDB global tables and cross-region RDS replication. The API layer in each region was active, and Route 53 geo-proximity routing sent users to the nearest region. When eu-west-1 had a network partition, traffic automatically shifted to us-east-1 within 2 minutes because Route 53 health checks detected the degradation. Zero perceived downtime for users.

Architecture pattern:

bash
# DynamoDB Global Table setup: automatic multi-region replication
aws dynamodb create-global-table \
  --global-table-name bookings \
  --replication-group RegionName=us-east-1 RegionName=eu-west-1 \
  --billing-mode PAY_PER_REQUEST

# Route 53 with geo-proximity routing and health checks
resource "aws_route53_health_check" "us_east_primary" {
  type            = "HTTPS"
  resource_path   = "/health"
  fqdn            = "api-us-east.example.com"
  failure_threshold = 2
}

resource "aws_route53_record" "api" {
  zone_id = var.zone_id
  name    = "api.example.com"
  type    = "A"

  geoproximity_location {
    region      = "us-east-1"
    coordinates = [latitude, longitude]
    bias        = 0
  }

  geoproximity_location {
    region      = "eu-west-1"
    coordinates = [latitude, longitude]
    bias        = 0
  }
}

Cost: Double the infrastructure cost ($4,000–10,000+/month) because you're running full capacity in two regions. Also the most complex operationally: handling conflicts, managing distributed state, troubleshooting across regions.

When to use it: Only for mission-critical systems where downtime is literally not acceptable. Think payment gateways, real-time trading, emergency services.

Match the business: Recovery targets decide the strategy

I've seen engineers spend weeks architecting active-active setups for internal dashboards. That's the wrong conversation. You start with two numbers from your business stakeholders: Recovery Time Objective (RTO) and Recovery Point Objective (RPO).

RTO is "how long can we be down?" If your e-commerce platform goes down for 6 hours, you lose money but survive. If it's down for 24 hours, the business is in serious trouble. That RTO drives your strategy choice.

RPO is "how much data can we afford to lose?" A trading platform loses credibility if it loses even one trade record—RPO needs to be near-zero. A content publishing platform can lose 30 minutes of edits without major impact.

Real example: At a SaaS HR platform, we had this conversation with the product and finance teams. They said: "We can afford 4 hours of downtime, but we cannot lose any employee records or payroll data." That meant warm standby with real-time replication was perfect. We sized it appropriately, tested failover quarterly, and slept well. For their customer support portal (secondary system), we used backup and restore because losing 24 hours of support tickets was acceptable.

Write this down with your team. Don't guess. A 30-minute conversation with stakeholders saves you weeks of over-engineering or months of regret when a disaster happens and your recovery strategy is too slow.

Automate recovery: Infrastructure as code makes rebuilding possible

Manual recovery is slow, error-prone, and nearly impossible at 3 AM. Infrastructure as code (Terraform, CloudFormation, or CDK) means you can rebuild your entire environment from code in minutes.

Example: Instead of manually creating security groups, launching instances, configuring load balancers, and pointing DNS during a disaster, you run one command and Terraform rebuilds everything exactly as it was defined in code.

bash
# Disaster recovery automation: one command to rebuild the entire stack
terraform apply -var="environment=disaster-recovery" -var="scale=full" -auto-approve

# Or with CloudFormation
aws cloudformation create-stack \
  --stack-name prod-recovery \
  --template-body file://infrastructure.yaml \
  --parameters ParameterKey=Environment,ParameterValue=ProductionRecovery

Best practices:

  • Keep your infrastructure code in version control (Git), tested like application code.
  • Run a monthly "chaos engineering" test: actually trigger a disaster recovery deployment and verify everything works.
  • Parameterize your Terraform/CloudFormation so you can deploy to different regions and scales easily.
  • Test not just the infrastructure rebuild, but also the application deployment, database migrations, and warm-up of caches.
  • Document the exact runbook: which command to run first, what to verify, when to switch traffic.

I've seen teams with perfect infrastructure-as-code that never tested it. When a real disaster happened, the code was outdated, dependencies had changed, and recovery took three times longer than expected. Automation is worthless without practice.

Test it: A DR plan you've never tested is a hope

This is the non-negotiable part. Your disaster recovery strategy must be tested in real environments, regularly, with the actual team that would handle the real disaster.

What to test:

  1. Full failover: Restore from backups or activate the standby region. Verify all systems come up.
  2. Data integrity: Run data validation queries to confirm no corruption or missing records.
  3. Application health: Run synthetic tests against the recovered environment. Can the app serve API requests? Can it process transactions?
  4. Dependencies: Check that third-party services (payment processors, analytics, email services) still connect properly.
  5. Timing: Measure actual RTO and RPO. Did recovery take 2 hours or 5 hours? Is the time acceptable?
  6. Communication: Alert the team via Slack, post updates to the status page, practice how you'd communicate with customers. This is often the hardest part.

Test schedule: I recommend quarterly full disaster recovery drills for critical systems. Pick a day, run the failover in a staging environment first, then declare an incident and execute the real recovery in a controlled window. Record what went wrong, fix it, and repeat next quarter.

Real scenario: A payment processing platform I worked on discovered during their first DR test that their standby database read replica had stale connection strings hardcoded in configuration files. Application failover worked, but the app couldn't connect to the standby database. Had this been a real disaster, they would have had no failover at all. The test saved them. They fixed the issue, added it to their runbook, and now all config comes from environment variables and AWS Systems Manager Parameter Store.

Common mistakes

  • Over-engineering for the business need: Building active-active for a tool that only internal staff uses. Start cheap, upgrade only if RTO/RPO demands it.
  • Never testing the plan: A DR strategy on paper is just documentation. If you've never executed it, it won't work when it matters.
  • Forgetting about application-level recovery: Restoring the database doesn't help if your application code has a critical bug or deploys a broken schema migration. Test the full application stack.
  • Not automating the recovery: Manual steps during a disaster create delays and inconsistencies. Use infrastructure-as-code and automated deployment pipelines.
  • Ignoring cross-region latency and data transfer costs: Multi-region setups incur data transfer fees. A warm standby or active-active might cost way more than you expect in egress charges.
  • Assuming backups work without verifying them: I've seen teams keep daily backups for months only to discover the backups were corrupted. Restore from backup regularly to verify they're actually usable.

Key takeaways

  • Disaster recovery strategies exist on a spectrum: backup-and-restore (cheap, slow) to active-active (expensive, fast). Pick the one that matches your RTO and RPO targets, not your engineering preference.
  • Start with the business: ask "How long can we be down?" and "How much data can we lose?" Let those answers drive your strategy.
  • Infrastructure-as-code is non-negotiable. You cannot reliably recover manually at 3 AM. Your infrastructure must be reproducible from code.
  • Test your DR plan quarterly, full-stack, with timing measurements. A plan you've never executed is just hope.
  • Common failures are often application-level (stale config, schema mismatches, dependency failures), not just infrastructure. Test end-to-end.
  • Watch your data transfer and compute costs in multi-region setups. Active-active is powerful but expensive.
  • Keep your backups verified, your recovery runbooks documented, and your team trained. Disaster recovery is a team sport, not a technical one.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles