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 we've hit.
The textbook answer to "how do I survive a region outage?" is "go multi-region." The textbook answer to "active-active vs active-passive?" is usually a flowchart. The reality is messier — every component in your stack makes a different choice, and the architectural simplicity of one pattern doesn't help when your database can't follow it.
We run a multi-region production environment across two AWS regions. Some pieces are active-active; some are active-passive; some are single-region. This is the framework we use and the failures that shaped it.
Active-Active. All regions serve traffic simultaneously. Each region has the full stack, capable of handling all traffic on its own. Traffic is routed by latency, by tenant, or by round-robin. Region failure = automatic failover, often invisible to users.
Active-Passive. One region serves all traffic. The other is a standby, kept in sync but not serving. Region failure = controlled failover (manual or automated) to the passive region.
Active-active is more resilient, more expensive, more complex. Active-passive is cheaper, simpler, but slower to recover.
Components where active-active makes sense:
Stateless services (compute). Easy. Run identical service deployments in both regions; the load balancer routes traffic. No coordination needed. A region going down just means traffic shifts.
Read-heavy data with eventual consistency. Cached reads, search indexes, CDN. Replicate to both regions; clients read locally. Slight staleness OK.
Geo-distributed data. When users in one region's data primarily lives in that region (think: GDPR-required regional data residency), each region is largely independent and active-active is natural.
Stateless event consumers (with idempotency). Both regions consume from the same event source; idempotent processing means double-delivery is benign.
For these, active-active is straightforward and adds resilience.
The Postgres-shaped problem. Active-active relational databases are operationally painful:
For most teams running standard Postgres / MySQL, the database is active-passive even if everything else is active-active. Writes go to the primary region; reads can be local; failover is manual or scripted.
We're in this camp. Postgres is active-passive (primary in us-east-1, replica in us-west-2). Application is active-active in front of it (both regions write to the same Postgres in us-east-1). Cross-region database latency adds ~70ms to write paths in us-west-2; we live with it.
| Component | Pattern | Notes |
|---|---|---|
| Web tier (stateless) | Active-active | Independent in each region |
| API tier (stateless) | Active-active | Independent in each region |
| Postgres (primary DB) | Active-passive | Primary in us-east-1; warm standby in us-west-2 |
| Read replicas | Active-active | One per region; reads served locally |
| Redis (cache) | Per-region active | Each region runs its own cache; no cross-region replication |
| S3 (storage) | Active-active | Cross-region replication; clients write to local |
| Kafka | Active-passive | Primary cluster in one region; mirror in other |
| Search (Elasticsearch) | Active-active | Index in both regions; writes dual-routed |
The pattern: stateless and eventually-consistent things go active-active. Strongly-consistent stateful things go active-passive. Failover for the active-passive components is the disaster recovery exercise.
Active-active sounds great until you think about consistency:
us-east-1, then reads. If their read goes to us-west-2 and replication is delayed, they see stale data.Resolutions exist (CRDTs, vector clocks, last-write-wins, application-level conflict resolution), but each is operational complexity and possible user-visible surprise. We avoided the problem by keeping our write-path active-passive.
Active-passive is only valuable if failover actually works. We test ours quarterly.
The exercise:
Total exercise time: ~2 hours. Real downtime if we did this in anger: ~10 minutes if we move fast.
What we learn every time:
The discipline of doing the exercise is what turns active-passive from "we have a standby" to "we can actually fail over." Active-passive without exercise is theater.
Cross-region latency. ~70ms between us-east-1 and us-west-2. Every cross-region call (web tier in us-west-2 writing to Postgres in us-east-1) adds that. It compounds with N calls per request. Architect around it: batch writes, use local caches.
Asymmetric failure modes. A region rarely fails completely. Often a single AZ degrades, or a specific service has issues. Multi-region helps with full-region outages; it doesn't help with partial degradation. Some of our worst incidents have been partial.
Cost. Multi-region roughly doubles infrastructure cost. The cost is justified for tier-1 user-facing services; less so for internal tools.
Operational complexity. Two of everything. Two sets of dashboards, two sets of alerts, two deployment targets. Operational surface area grows.
Replication-lag-triggered data loss. Active-passive failover with non-zero replication lag means some writes from before the failover are lost. We've held data loss under 5 seconds; getting to 0 requires synchronous replication, which costs latency on every write.
Honest list:
We have plenty of services that are single-region. The multi-region investment is reserved for the user-facing critical path.
Active-active is mostly active-passive in disguise. Once you trace any active-active design, there's a stateful component somewhere that's actually active-passive. The "active-active" label often applies only to the stateless tier.
The bigger reliability win is intra-region. Most outages we've seen are AZ-level, not region-level. Multi-AZ deployments within a region catch most cases at a fraction of the multi-region cost. Multi-region is for the very tail.
Disaster recovery testing is harder than building DR. Standing up the standby region is one project. Running quarterly exercises that prove it works is forever.
Multi-region is one of those decisions where the architectural choice (active-active vs active-passive) is the easy part. The hard part is operating it: failover discipline, drift detection, the second of everything. Be honest about whether the resilience pays for the complexity. For us, on the user-facing critical path, it does. Elsewhere, it doesn't.
Get the latest tutorials, guides, and insights on AI, DevOps, Cloud, and Infrastructure delivered directly to your inbox.
They solve different problems. RAG injects knowledge; fine-tuning changes behavior. The decision criteria, the hybrid pattern, and what we'd do over.
The "three pillars" framing misses the point — what matters is correlating across them. The patterns that earn their place and the tooling decisions that pay back.
Explore more articles in this category
The observability market is huge and the pricing is a minefield. This is the map to the tools that matter, what each is best at, and how to avoid a runaway bill.
Cloud bills grow quietly until someone asks why. This is the map for cutting spend without cutting reliability: where the money actually goes, the levers that work, and the tools worth paying for.
Static keys leak. The question isn't if but how fast you notice and how clean your response runbook is when the pager goes off.
Evergreen posts worth revisiting.