Scalability & Architecture Patterns
Multi-Region Architecture
Running a system across multiple geographic regions buys lower latency for distant users and survival of a whole-region outage — at the cost of cross-region data consistency and a much harder operational story.
- Active-passive: one region serves traffic, another stands by as a warm replica — simple, but standby capacity sits mostly idle and failover has real recovery time
- Active-active: multiple regions serve traffic simultaneously — better latency and utilization, but every region can accept writes, and those writes must be reconciled
- Cross-region replication is inherently asynchronous at useful latencies — tens to low-hundreds of milliseconds between continents makes synchronous cross-region writes crater latency
- GeoDNS or anycast routes each user to their nearest healthy region; health checks must distinguish "degraded" from "down" to avoid routing users into a bad region
- Conflict resolution — last-writer-wins, CRDTs, or an explicit merge function — is unavoidable in active-active: someone decides what happens when two regions accept conflicting writes for the same record
- RPO (how much data can be lost) and RTO (how long until service is restored) are the two numbers that should drive active-passive vs active-active, not architectural preference
| Active-Passive | Active-Active | |
|---|---|---|
| Write path | primary region only | any region |
| Remote-user latency | higher — routed to primary | lower — served by nearest region |
| Failover time | real — standby must take over | none — other regions already serving |
| Conflict handling | not needed — single writer | required — concurrent writes across regions |
| Idle capacity | standby mostly unused | all regions doing useful work |
Record resolve(Record local, Record remote) {
return local.updatedAt().isAfter(remote.updatedAt()) ? local : remote;
}