Multi-region active-active architecture
How to run a truly active-active multi-region system, conflict resolution strategies, global load balancing, the latency vs. consistency trade-off, DNS failover, and what active-active really costs.
The Problem Statement
Interviewer: "Your company is expanding globally. Today you run a single region in us-east-1. You need to serve users in Europe and Asia with low latency, and you cannot afford downtime if an entire AWS region goes offline. Walk me through how you would design an active-active multi-region architecture. What are the hardest problems you will face?"
This question tests three things: whether you understand the difference between active-active and active-passive (and why active-active is dramatically harder), how you handle concurrent writes to the same data in multiple regions (conflict resolution), and whether you can reason about the real costs and trade-offs of multi-region (it is not just "deploy to two regions").
Most candidates describe active-passive failover and call it active-active. The strong answer explains why multi-writer conflict resolution is the hard problem, walks through the global load balancing layer, discusses database topology choices (and their trade-offs), and acknowledges the cost: active-active is roughly 2x+ the infrastructure cost with significant operational complexity.
This question appears in interviews for systems at Amazon, Google, Stripe, and every company that runs at global scale. It is one of the most important architecture topics for senior-level interviews.
Clarifying the Scenario
You: "Great question. Before I jump into the design, I want to make sure I understand the requirements."
You: "When you say 'active-active,' do you mean both regions serve reads and writes simultaneously, or is it acceptable for writes to go to one region with reads distributed?"
Interviewer: "True active-active. Both regions accept reads and writes."
You: "Got it. That changes the problem significantly because of write conflicts. What kind of data are we talking about? User profiles, transactions, content?"
Interviewer: "Think of a typical SaaS application. User data, project data, collaboration features. A mix of strong-consistency needs (billing) and eventual-consistency-tolerant data (user settings)."
You: "And what is the availability target? Are we designing for regional failure (entire AWS region goes down) or also for partition tolerance between regions?"
Interviewer: "Regional failure. If us-east-1 goes down, European users should not notice."
You: "OK. I will structure my answer in four parts: the global load balancing layer that routes users to the right region, the data replication and conflict resolution strategy (which is the hardest part), the database topology choices and their trade-offs, and the operational cost of running active-active."
My Approach
I break this into five parts:
- Active-active vs. active-passive comparison: Why active-active is fundamentally different and when you actually need it (most companies do not).
- Global load balancing and traffic routing: GeoDNS, Anycast, latency-based routing, and how users get assigned to regions.
- Conflict resolution in multi-writer systems: The core hard problem. Last-writer-wins, CRDTs, and application-level merge strategies.
- Database topology for multi-region: CockroachDB/Spanner (strong global consistency) vs. Cassandra/DynamoDB (eventual consistency). The trade-off is always latency vs. consistency.
- What active-active actually costs: 2x+ infrastructure, cross-region data transfer fees, operational complexity, and the team size required to run it.
The Architecture
Here is how the system works:
-
GeoDNS routes users to the nearest region. A user in Berlin resolves your domain to the eu-west-1 IP address. A user in Tokyo resolves to ap-northeast-1. Route 53 or Cloudflare DNS does this using latency-based routing or geographic routing. Health checks every 10 seconds detect regional failures and automatically reroute traffic.
-
Each region is a full, independent stack. Load balancers, stateless app servers, a local cache layer (Redis), and a local database replica. The user's request never leaves the region for reads, and writes are accepted locally.
-
Database replication is bidirectional and asynchronous. Each region's database replicates changes to every other region. Async replication means writes are fast (acknowledged locally) but there is a replication lag window of 100-300ms where regions may have different views of the data.
-
Conflict resolution handles concurrent writes. When two regions write to the same record during the replication lag window, the system must decide which write wins. This is the core hard problem.
The first thing to internalize: in active-active, every region accepts writes independently. There is no single source of truth during the replication lag window. If you are not comfortable with that, you need either active-passive (single writer) or synchronous replication (which kills latency).
Most companies do not need active-active. Active-passive with fast failover (DNS TTL of 60s, pre-warmed standby) gives 99.95%+ availability and avoids the write-conflict problem entirely. Only go active-active if you need both sub-100ms write latency globally AND cannot tolerate any region being "standby."
Conflict Resolution in Multi-Writer Systems
This is the section that separates a senior answer from a junior answer. Anyone can draw two regions with arrows between them. The hard part is: what happens when two users in different regions update the same record at the same time?
Think of it like two people editing the same Google Doc paragraph simultaneously, except they are on different continents and their changes take 200ms to reach each other. During that 200ms window, both edits exist independently and both are "correct" locally.
The three main strategies:
| Strategy | How It Works | Pros | Cons | Best For |
|---|---|---|---|---|
| Last Writer Wins (LWW) | Use timestamps. Most recent write survives. | Simple. No application changes. | Clock skew causes data loss. Silent overwrites. | Ephemeral data: sessions, counters, caches |
| CRDTs | Data structures that merge without conflict | Mathematically guaranteed convergence | Limited data types. Complex to implement. | Counters, sets, registers, flags |
| Application-level merge | Business logic decides the winner | Most correct for the domain | Requires per-entity merge logic | Shopping carts, collaborative docs, billing |
Last Writer Wins is the most common approach because it requires zero application changes. You add a timestamp column to every row, and when a conflict is detected during replication, the row with the later timestamp survives. The loser is silently dropped.
The problem: clocks are not perfectly synchronized across regions. NTP gives you millisecond-level accuracy at best, and two writes at "the same time" have indeterminate ordering. In practice, this means a small percentage of concurrent writes will resolve incorrectly. For user profile bios, this is annoying but survivable. For bank account balances, this is catastrophic.
CRDTs (Conflict-free Replicated Data Types) are data structures designed to merge without conflicts. A G-Counter, for example, lets each region maintain its own counter. The "total" is the sum of all region counters. Two regions incrementing simultaneously never conflict because each increment goes into a separate slot.
CRDTs are mathematically elegant but limited in what data types they support. You can build conflict-free counters, sets (add-only or add/remove), registers (LWW or multi-value), and flags. You cannot easily build a conflict-free relational row update.
Application-level merge is the most flexible and the most work. You write domain-specific conflict resolution logic for each entity type. A shopping cart merges by union (add all items from both writes). A billing record rejects concurrent updates and retries. A user profile might keep the most recent value for each field independently rather than overwriting the entire record.
For your interview: state that you would use a mix. LWW for low-stakes data (user settings, preferences), CRDTs for counters and flags (like counts, feature toggles), and application-level merge for business-critical data (billing, inventory).
Continue Reading with Premium
Unlock this article and every other in-depth system design guide on the platform with SDEpedia Premium.