Skip to main content
Multi-Region: Active-Active vs Active-Passive, And What We Actually Run

Multi-Region: Active-Active vs Active-Passive, And What We Actually Run

KU
• 8 min read•Updated •24 views

The architectural choice is presented as binary; the practical answer is "depends on the workload." The patterns that earn their place and the failure modes to plan for.

Key takeaways

  • Run stateless tiers active-active and keep the relational database active-passive unless you adopt a database built for multi-region writes.
  • Active-active cuts recovery time to near zero but forces you to solve write conflicts.
  • Active-passive is cheaper and simpler, with an RPO of seconds on Aurora Global Database, but only works if you rehearse failover.

Run the stateless tiers active-active and the primary database active-passive. Active-active serves traffic from every region and recovers almost instantly, but forces you to resolve concurrent writes. Active-passive keeps one writer and a standby, costs less, and loses seconds of data on an unplanned failover. Almost every "active-active" system is this hybrid once you trace the data.

Verified against

Amazon Aurora Global Database (switchover, failover, write forwarding and rds.global_db_rpo), Amazon Application Recovery Controller and Route 53, against the AWS Aurora User Guide and the AWS "Disaster Recovery of Workloads on AWS" whitepaper. Checked October 2026.

The patterns, on one page

AWS's disaster recovery whitepaper describes four strategies on a cost-versus-recovery spectrum. Active-passive covers the first three; only the last serves traffic everywhere.

StrategyTraffic in DR regionRecovery timeData loss (RPO)Relative costWrite conflicts to solve
Backup and restoreNoneLongest: redeploy, then restoreSince last backupLowestNo
Pilot lightNone (data live, compute off)Longer: switch compute on, scale outSeconds with continuous replicationLowNo
Warm standbyNone, or scaled-downShort: scale up onlySecondsMediumNo
Multi-site active/activeAll regions serveNear zero for most disastersNear zero, except corruptionHighestYes

Active-active means every region runs the full stack and takes live traffic, routed by latency, geography or tenant. Active-passive means one region serves while the other holds replicated data and some or all of the stack, ready to be promoted. The whitepaper's point that most teams miss: with active-active "there is no such thing as failover," so testing shifts to whether the surviving regions can absorb the load.

Where active-active fits

  • Stateless services. Identical deployments in each region behind latency-based routing. A region going down just shifts traffic.
  • Read-heavy, eventually consistent data. Caches, search indexes, CDN content. Replicate everywhere and read locally.
  • Partitioned data. When each user's data lives in one home region (data residency is the usual driver), regions are largely independent. AWS calls this write partitioned.
  • Idempotent event consumers. If processing the same event twice is harmless, both regions can consume.

Where active-active is hard, and we punt

The relational database is the problem. Two writes to the same row in two regions need a winner, and every resolution (last-writer-wins, CRDTs, application merge logic) is a user-visible surprise waiting to happen. Your options:

  • Write global. All writes go to one region. Aurora Global Database fits: secondaries serve local reads, and write forwarding lets a secondary forward write statements to the primary so the application talks to one endpoint per region. The primary stays the source of truth, so you still pay cross-region latency on each forwarded write.
  • Write local. DynamoDB global tables accept writes in every region and reconcile concurrent updates with last-writer-wins.
  • Distributed SQL (Spanner, CockroachDB, YugabyteDB) is built for multi-region writes, but moving to it is a re-architecture.

We are in the write-global camp. Postgres runs active-passive with the primary in us-east-1 and a secondary in us-west-2; the application tier runs active-active in front of it. West-coast write paths pay the cross-region round trip, so we batch writes and keep reads local. Routing reads to replicas has its own trap, read-your-own-writes, covered in Postgres read replicas without stale-data bugs.

What we run, component by component

ComponentPatternNotes
Web and API tiersActive-activeIndependent in each region
Postgres (primary DB)Active-passiveWriter in us-east-1; promotable secondary in us-west-2
Read replicasActive-activeReads served locally, lag-aware routing
Redis (cache)Per-regionNo cross-region replication; caches warm independently
S3Active-activeCross-region replication, partitioned writes
KafkaActive-passivePrimary cluster plus mirror
SearchActive-activeIndex in both regions; writes dual-routed

Stateless and eventually consistent goes active-active. Strongly consistent state goes active-passive. Failover for the passive pieces is the disaster recovery plan.

The failover runbook (the part that earns its keep)

Active-passive is only worth something if failover works, so rehearse it on a schedule. For planned drills and failback, use an Aurora switchover: it waits for the secondary to sync, so RPO is 0, and on Aurora PostgreSQL 16.8+ or Aurora MySQL 3.09+ read/write recovery is typically under 30 seconds. For a real outage, use failover with --allow-data-loss, which promotes without waiting and loses whatever had not replicated.

code
# Check how far behind the secondary is (milliseconds) before choosing a target
$ aws cloudwatch get-metric-statistics --region us-west-2 --namespace AWS/RDS \
    --metric-name AuroraGlobalDBRPOLag --dimensions Name=DBClusterIdentifier,Value=app-west \
    --start-time 2026-10-31T09:00:00Z --end-time 2026-10-31T09:10:00Z --period 60 --statistics Maximum

# Planned drill: zero data loss
$ aws rds --region us-east-1 switchover-global-cluster --global-cluster-identifier app-global \
    --target-db-cluster-identifier arn:aws:rds:us-west-2:123456789012:cluster:app-west

# Real outage: promote now, accept replication lag as loss
$ aws rds --region us-west-2 failover-global-cluster --global-cluster-identifier app-global \
    --target-db-cluster-identifier arn:aws:rds:us-west-2:123456789012:cluster:app-west --allow-data-loss

Move traffic with a data-plane control. AWS's whitepaper warns that editing Route 53 weights is a control-plane operation and recommends Application Recovery Controller routing controls, which act like switches on Route 53 health checks. Point applications at the Aurora global writer endpoint so the database cutover doesn't need a config change, and drop client DNS caching to around 5 seconds, which is what AWS suggests to limit split-brain writes.

What every drill finds: a hard-coded hostname for the old primary, connection pools holding stale hosts, a parameter group on the secondary that drifted from the primary, alarms and dashboards that only existed in the old region. Chaos engineering game days are the right format, and testing database restores covers the corruption case replication can't fix.

Failure modes, with the signals they leave

  • Replication-lag data loss. After failover-global-cluster, Aurora snapshots the old primary as rds:unplanned-global-failover-<cluster>-<timestamp> so you can recover unreplicated rows. Know where to look before you need it.
  • Commits stall in the primary. If rds.global_db_rpo is set (minimum 20 seconds) and every secondary falls behind it, Aurora PostgreSQL blocks commits until one catches up. AWS recommends leaving it at default in two-region setups.
  • Split brain. Write fencing on managed failover is best-effort; take writers offline and use the global endpoint.
  • Partial failure. A region rarely dies cleanly. One degraded AZ or service is more common, as the EU-SOUTH-2 single-AZ packet loss showed, and multi-region does nothing for it unless you decide to fail over.

Where this breaks

Multi-region roughly doubles the stack you operate: two of every dashboard, alert and deployment target, plus cross-region transfer charges, which feed straight into the reserved, savings plan and spot math. It is the wrong answer for small ops teams, internal tools and anything where "restore from backup in four hours" is acceptable. Most outages are AZ-level, and multi-AZ inside one region catches those at a fraction of the cost. Replication also faithfully copies corruption and accidental deletes, so backups remain mandatory.

Questions people ask

What is the difference between active-active and active-passive?

In active-active, every region serves live traffic and holds a full copy of the stack, so losing one region just shifts users elsewhere. In active-passive, one region serves all traffic while another holds replicated data and standby capacity, and recovery means promoting it. Active-active costs more and forces you to solve concurrent writes; active-passive is simpler but has a recovery window.

Is active-active better than active-passive for disaster recovery?

Only if you can afford it and your data model tolerates multi-region writes. Active-active brings recovery time close to zero, but the AWS DR whitepaper notes data corruption still requires restoring from backups. For a relational database, active-passive with a rehearsed failover, measured in seconds of RPO on Aurora Global Database, is usually the better trade.

How much data do you lose in an Aurora Global Database failover?

For an unplanned failover, AWS says RPO is typically measured in seconds and depends on replication lag at the moment of failure, visible in the AuroraGlobalDBRPOLag metric. A planned switchover waits for the secondary to synchronize, so RPO is zero. On Aurora PostgreSQL you can cap lag with rds.global_db_rpo, at the cost of blocking commits.

The call we'd make

Go multi-region only for the user-facing critical path, and even there make it a hybrid: stateless tiers active-active, the relational database active-passive on a managed global database with a rehearsed switchover, and traffic moved by a data-plane control rather than a DNS edit made during the outage. Alert on replication lag with burn-rate style SLO discipline. Everything else stays single-region with tested backups. Active-passive without regular drills is theater.

Sources

Explore topics:Cloud
React
Share this post
Cite this article
Plain text

Kiril Urbonas (2026). Multi-Region: Active-Active vs Active-Passive, And What We Actually Run. DevOpsNess. Updated 2026-10-31. https://www.devopsness.com/blog/multi-region-active-active-vs-active-passive

Markdown

[Multi-Region: Active-Active vs Active-Passive, And What We Actually Run](https://www.devopsness.com/blog/multi-region-active-active-vs-active-passive) (Kiril Urbonas, DevOpsNess, updated 2026-10-31)

KU

Kiril Urbonas

AI Engineer

585 articles
View all articles by Kiril Urbonas

You might have missed

Evergreen posts worth revisiting.