TL;DR

1. The problem: why run in more than one region?

Imagine every Instagram server — all the application services, the sharded PostgreSQL User DB, the Cassandra clusters, Redis caches, Kafka — lives in a single region in Virginia. Three things go wrong:

Multi-region architecture addresses all three, but it's one of the hardest things in system design because the speed of light makes cross-region coordination slow — and the CAP theorem says that during a partition between regions you must choose between consistency and availability.

🧠 Analogy A bank with a single branch and a single vault is ruined if that building floods. So it opens branches in several cities (lower latency for customers, survives a flood in one city). But now an account can be touched in two cities at once — it needs rules about which branch "owns" each account (home region), how quickly other branches learn about deposits (replication lag), and what happens if two branches approve withdrawals at the same moment (conflicts). It also keeps off-site archives of the ledgers (backups) and periodically rehearses opening a branch with the archives (restore tests and DR drills).

2. Vocabulary: regions, zones, data centers, cells

🏢 Data center

One building (or campus) with power, cooling, and network. A single failure domain for power/cooling incidents.

🧩 Availability zone (AZ)

Cloud term: one or more data centers with independent power and networking, a few km from other AZs in the same region. Low-latency links (~1 ms) between AZs.

🌍 Region

A geographic area containing several AZs (e.g. us-east, eu-west). Regions are hundreds to thousands of km apart; latency between them is tens to hundreds of ms.

🧱 Cell

A complete, independent copy of a service stack serving a fixed subset of users. Limits the "blast radius" of failures and bad deploys (section 10).

Multi-AZ deployment (replicas in 2–3 zones of one region) protects against a data-center failure with almost no latency cost — synchronous replication is affordable at ~1 ms. Multi-region protects against region-wide events, but replication must usually be asynchronous. Most systems do both: multi-AZ inside each region, multi-region on top.

Route (approx., assumption)Round-trip time
Same AZ< 0.5 ms
Between AZs in a region~1–2 ms
US East ⇄ US West~60–70 ms
US East ⇄ Western Europe~75–90 ms
US East ⇄ Singapore~200–240 ms

3. Active-passive vs active-active

ACTIVE-PASSIVE ACTIVE-ACTIVE 📱 All users Region A (active)serves 100% trafficprimary DB (writes) Region B (passive)idle / minimalreplica DB 📱 US users 📱 EU users Region US (active)serves US trafficwrites for US-homed users Region EU (active)serves EU trafficwrites for EU-homed users only on failover async replication → replication both ways + simple: one writer, no conflicts − standby capacity mostly idle − failover is rare, slow, scary + low latency everywhere, no idle capacity + failover = shift traffic (well-exercised) − write routing, lag and conflicts
Active-passive: one region does all the work while a standby waits. Active-active: every region serves live traffic and data is replicated between them.
Active-passiveActive-active
TrafficAll in the primary region; standby gets none (or only read traffic, "hot standby").All regions serve users, usually the nearest.
WritesSingle writer region — no conflicts.Either partitioned (each record has one home region) or multi-writer (needs conflict resolution).
FailoverPromote standby DBs, scale up standby compute, flip DNS. Minutes to hours; rarely exercised so often goes wrong.Shift traffic away from the failed region; surviving regions must have headroom to absorb it.
CostPaying for a standby that does nothing (unless kept small).All capacity is useful, but each region needs spare headroom (e.g. 3 regions each run at ≤ 66% so any two can carry the full load).
Latency benefitNone for distant users.Yes — users served nearby.
ComplexityLower.Much higher (data placement, routing, consistency).
💡 Headroom math With N active regions, to survive the loss of one region the remaining N−1 must carry 100% of traffic. So each region must normally run at no more than (N−1)/N of capacity: 50% with 2 regions, 67% with 3, 80% with 5. More regions = less wasted headroom — one reason large companies run many.

4. RPO and RTO

Disaster-recovery requirements are written as two numbers:

         last good copy                disaster                    service restored
               │                          │                               │
  ─────────────●══════════════════════════✖═══════════════════════════════●──────► time
               │◄──── data lost (≤ RPO) ─►│◄────── downtime (≤ RTO) ─────►│

  Async replication with 2 s lag        →  RPO ≈ seconds
  Nightly backup at 02:00, crash 18:00  →  RPO = 16 hours
  Automated DNS failover in 3 min       →  RTO ≈ minutes (+ DNS TTL)
  Restore 50 TB from backup at 1 GB/s   →  RTO ≥ 14 hours just to copy data

Different data deserves different targets. For Instagram (assumptions): DMs and posts need RPO of seconds; the like counter can tolerate approximate recovery (rebuild from the likes table); the analytics lake can be hours behind; the feed cache needs RPO = ∞ — it can be rebuilt from source data and doesn't need backup at all.

5. Disaster-recovery strategies

Cloud providers popularised four standard DR strategies. They form a ladder: each step lowers RPO/RTO and raises cost.

StrategyWhat's running in the recovery regionTypical RPOTypical RTOCost
Backup & restoreNothing but backups (DB snapshots, object-storage copies). Infra is rebuilt from code (Terraform etc.) when disaster strikes.Hours (time since last backup)Hours to days💲 lowest
Pilot lightCore data continuously replicated (DB replicas running); application servers defined but switched off or tiny.Seconds–minutes (replication lag)Tens of minutes to hours (start & scale compute)💲💲
Warm standbyA fully working but scaled-down copy of the whole stack; can serve some traffic immediately; scale up on failover.Seconds–minutesMinutes💲💲💲
Multi-site active-activeFull production in every region, all serving traffic.Near zero to seconds (depends on sync vs async)Seconds to minutes (shift traffic)💲💲💲💲 highest

Choose per system, based on the business cost of downtime and data loss. An internal reporting tool can live with backup & restore; the Instagram feed and DMs need active-active; the user DB might be active-passive per shard (one primary region per shard, replicas elsewhere) inside an overall active-active deployment.

6. Cross-region data replication and lag

Stateless services (the Feed, Upload and Search services) are easy to run in many regions — just deploy them. State is the hard part. Every stateful store needs a cross-region replication strategy (see Replication for the fundamentals).

6.1 Synchronous vs asynchronous

Synchronous cross-regionAsynchronous cross-region
Write acknowledged whenCommitted in ≥ 2 regions (or a quorum across 3+).Committed locally; shipped to other regions in the background.
Write latency+ one cross-region RTT per write (e.g. +80 ms US⇄EU).Unchanged (local).
RPO on region loss0 — no acknowledged write is lost.= replication lag at the moment of failure (usually ms–seconds; can be minutes under load).
Availability during partitionWrites stall if the quorum can't be reached (CP).Writes continue (AP); regions diverge temporarily.
ExamplesGoogle Spanner, CockroachDB, Cassandra with EACH_QUORUM, Raft/Paxos groups spanning regions.PostgreSQL/MySQL streaming replicas in other regions, Cassandra LOCAL_QUORUM + async cross-DC, S3 Cross-Region Replication, Kafka MirrorMaker.

A common middle ground is to spread a consensus group across three nearby regions (e.g. US-East, US-Central, US-West): each write waits for 2 of 3, adding ~20–40 ms rather than 80+, while surviving the loss of any one region with RPO = 0. Most social-media data, though, uses asynchronous replication and accepts a small RPO — losing the last second of likes in a once-a-decade disaster is acceptable; adding 80 ms to every like is not.

6.2 Living with replication lag

Replication lag is how far behind a replica is — measured in seconds or in log position. It causes user-visible anomalies:

Monitor lag continuously and alert on it — it is literally your current RPO. A replica 10 minutes behind means a failover now loses 10 minutes of data.

7. Write routing and conflict handling

7.1 Home region per user (partitioned writes)

The simplest way to be active-active without conflicts is to ensure each record has exactly one writable home at any time. Assign each user a home region (usually where they mostly connect from); all writes to data owned by that user go to that region's primary, and other regions hold read replicas.

 user 184467 (home = EU)          user 99021 (home = US)
 ─────────────────────────        ─────────────────────────
 EU region:  PRIMARY  ✎           EU region:  replica  👁
 US region:  replica  👁           US region:  PRIMARY  ✎

 A US-homed user travelling in Europe:
   reads  → EU region (local replicas, fast)
   writes → forwarded to US primary (+~80 ms, rare enough to be fine)

7.2 When multiple regions can write the same data

Some systems allow writes to the same record in multiple regions (multi-leader / leaderless), for availability during partitions. Then conflicts are inevitable and need a resolution strategy:

TechniqueHowGood for / caveat
Last-writer-wins (LWW)Each write carries a timestamp; the highest wins everywhere.Simple (Cassandra's default). Silently drops concurrent writes; clock skew can make an older write win.
Version vectorsTrack per-region version counters to detect true concurrency, keep both "siblings", let the app merge.Correct detection; app must implement merge.
CRDTsData types whose concurrent updates always merge deterministically (counters, sets, registers).Like counts as a PN-counter (each region keeps its own +/− tallies; total = sum). Followers as an add/remove set.
Application-level rulesDomain logic, e.g. "a block always wins over a follow", "a delete wins over an edit".Safest for security-sensitive data.
Avoid conflictsRoute all writes for a key to one home region (7.1).Most common in practice.
# PN-counter CRDT for a post's like count, replicated across regions
state = {"US": {"inc": 1040, "dec": 12}, "EU": {"inc": 388, "dec": 3}, "APAC": {"inc": 905, "dec": 9}}
value = sum(r["inc"] - r["dec"] for r in state.values())   # 2309
merge(a, b) = per region: max(a.inc, b.inc), max(a.dec, b.dec)   # commutative, idempotent

8. Global traffic management

How does a user's phone reach the right region, and how is traffic moved away from a failed one?

📱 AppSingapore
→anycast / GeoDNS
Edge PoPTLS termination
→private backbone
Global LBpick healthy region
→
Region APACor next-nearest if down

9. Failover, failback and drills

9.1 A failover runbook

A runbook is a written, rehearsed procedure. A regional failover for an Instagram-like active-active system might be:

  1. Detect & declare. Alerts fire (error rate, health probes). The incident commander confirms it's a regional problem (not a bad deploy everywhere — failing over won't fix that) and declares a failover. Automation can do this for clear-cut cases; many organisations keep a human decision for full-region failover to avoid flapping on false positives.
  2. Check capacity. Confirm surviving regions have headroom; pre-emptively scale them up; shed low-priority load (background jobs, prefetch, batch analytics) to make room.
  3. Drain traffic. Set the failed region's weight to 0 in the global load balancer / withdraw anycast routes / update GeoDNS.
  4. Promote data. For shards whose primary was in the failed region, promote replicas in a surviving region to primary. Fence the old primaries (revoke their write permission/lease) so that if the failed region comes back unexpectedly it can't accept writes — otherwise you get split brain: two primaries diverging.
  5. Re-point async systems. Kafka producers/consumers, cron jobs, and batch pipelines that ran in the failed region are started elsewhere.
  6. Verify. Dashboards for error rates, latency, replication health; synthetic user journeys (log in, load feed, post, DM).
  7. Communicate. Status page, internal updates.

9.2 Failback

Failback — returning to the original region — is often riskier than failover because it's done less urgently and with less practice. The recovered region's databases are stale and may contain un-replicated writes made just before the failure (the RPO window). Steps: rebuild the old primaries as replicas of the new primaries (don't just "turn them back on"); reconcile or discard the orphaned writes (log them for review); wait until lag is near zero; shift traffic back gradually (1% → 10% → 50% → 100%); move primaries back during a quiet period.

9.3 Drills

A failover plan that has never been executed will fail: credentials expire, scripts reference deleted hosts, a "stateless" service turns out to depend on a config store in the failed region, and surviving regions turn out to lack capacity. The only cure is regular drills in production:

10. Cell-based architecture and blast radius

Blast radius is how many users a single failure can affect. A region failover limits blast radius to "everyone in that region" — still tens or hundreds of millions of people. And many outages aren't regional disasters at all: they're a bad deploy, a poison request, or a runaway client that hits every replica of a service at once. Cells shrink the blast radius further.

📱 Requests (user_id) Cell routeruser_id → cell map (thin) Cell 1 services (all) DB shards + cache Cell 2 services (all) DB shards + cache Cell 3 ✖ bad deploy only its users hit DB shards + cache Cell N services (all) DB shards + cache
Cells: each cell is a full, independent stack for a slice of users. A failure or bad deploy in one cell affects only that slice (here ~1/N of users).

Regions, AZs, cells and shards are nested failure domains. A well-designed system asks, for each: "if this unit fails, what fraction of users is affected, and what happens to them?"

11. Backups: replication is not a backup

Replication protects against losing a machine or region. It does not protect against bad writes: if a bug or an attacker deletes or corrupts data, replication faithfully copies the damage to every replica within milliseconds. You need backups — point-in-time copies you can go back to.

11.1 The 3-2-1 rule

3️⃣ copies

Keep at least three copies of important data: production plus two backups.

2️⃣ media / systems

On at least two different storage systems or media types, so one bug or failure mode can't destroy both.

1️⃣ off-site

At least one copy in a different location (another region, another account) — ideally immutable (write-once, object lock) so ransomware or a compromised admin account can't delete it.

11.2 Backup techniques

11.3 Restore testing

"Backups don't matter; restores do." Many organisations discover during a disaster that backups were incomplete, corrupt, missing a table, or would take days to restore. Practice:

12. Data residency and GDPR

Data residency means keeping certain data within a geographic or legal boundary. The EU's GDPR does not, by itself, require that all EU data be stored in the EU; it restricts transfers of personal data outside the European Economic Area unless there's a legal basis (an adequacy decision, standard contractual clauses with extra safeguards, etc.). In practice, legal uncertainty around EU→US transfers (the 2020 "Schrems II" ruling invalidated the EU-US Privacy Shield; Meta was publicly fined €1.2 billion by the Irish regulator in 2023 over Facebook's EU-US transfers before a new EU-US Data Privacy Framework was adopted) has pushed many companies to localise more data. Other countries (e.g. Russia, China, India for some data categories) have their own localisation rules.

Architectural techniques:

13. How Instagram does multi-region

Instagram's public history is a textbook progression up the DR ladder (dates and details as publicly reported; internal specifics are not public):

  1. 2010–2012 — a single AWS region. The early Django + PostgreSQL + Redis + memcached stack ran on AWS in the US-East region. On 29 June 2012, severe storms caused a power failure in an AWS US-East data center; Instagram (along with Netflix and Pinterest) was widely reported to be down or degraded for many hours. With everything in one region and recovery depending on bringing that region back, the outage illustrated precisely the single-region risk in section 1, and it is often cited as a lesson in why critical services should not depend on a single data center or region.
  2. 2013–2014 — migration into Facebook's data centers. After the 2012 acquisition, Instagram publicly described a large migration ("Instagration") from AWS into Facebook's own data centers, completed in 2014 — moving a live service with hundreds of millions of users, its sharded PostgreSQL and Cassandra data, without a user-visible outage. Being inside Facebook's infrastructure gave Instagram access to Meta's networks, edge PoPs, tooling and data-center fleet.
  3. 2015 onwards — multiple data centers. Instagram's engineering blog publicly described expanding from one data center to several, and running across multiple regions: stateless Django application tiers deployed in each data center; Cassandra replicated across data centers with local-quorum reads/writes; PostgreSQL with a primary per shard in one location and replicas elsewhere, writes routed to the primary; and careful handling of cache invalidation across regions. This enabled serving traffic from multiple places and surviving the loss of a data center.
  4. Today — part of Meta's global infrastructure. Meta publicly describes running many data-center regions, a global edge network, and regular disaster-recovery drills (Storm) that take whole data centers offline — Instagram participates in these like other Meta products.
📸 Mapping it to the main diagram Every box in the architecture diagram exists in multiple regions. Stateless services (Upload, Feed, Search, DM, Stories) are deployed everywhere and are the easy part. The User DB (sharded PostgreSQL) has one writable primary per shard with cross-region replicas — writes for a shard go to its home. Cassandra stores (posts, comments, messages) replicate across regions with per-region quorums, accepting brief eventual consistency between regions. Redis feed caches are per-region and rebuildable — no cross-region backup needed. Object storage replicates photos and videos across regions, and the CDN keeps serving cached media even when an origin region is down. Kafka runs per region, with mirroring for streams that must be global (e.g. analytics). The numbers below are assumptions to reason with, not official figures.

Rough numbers (assumptions)

3 active regions, peak 1M API req/s total → ~333k req/s each
Survive loss of 1 region → each must handle 500k req/s → run at ≤ 67% of capacity
Write rate 50k writes/s, avg 1 KB → 50 MB/s replicated to each other region (~400 Mbps)
Async lag normally ~100–500 ms → RPO on sudden region loss ≈ 0.5 s × 50k = ~25k writes at risk
Restoring a 2 TB shard from backup at 400 MB/s ≈ 1.4 h → per-shard RTO if no replica

14. Trade-offs & common pitfalls

✅ Benefits

  • Survives data-center and region-wide disasters
  • Lower latency for users worldwide
  • Enables data-residency compliance
  • Maintenance and risky changes can be done region by region / cell by cell
  • Smaller blast radius for failures and bad deploys

⚠️ Costs

  • Much higher cost: duplicate infrastructure plus idle headroom
  • Consistency problems: replication lag, conflicts, read-your-writes
  • Cross-region bandwidth bills
  • Operational complexity: deploys, config, secrets, schema changes in many places
  • Failover itself is risky if not rehearsed (split brain, capacity shortfall)

Common pitfalls

15. Real-world technologies

TechnologyRoleWhen to use
AWS Route 53, Azure Traffic Manager, Google Cloud DNS, NS1GeoDNS, latency-based routing, health-checked failover recordsDNS-level traffic steering between regions.
AWS Global Accelerator, Google Cloud Load Balancing, Cloudflare, Azure Front DoorAnycast front doors, global load balancingFast, DNS-independent region failover.
Google Spanner, CockroachDB, YugabyteDBGlobally distributed SQL with consensus replicationStrong consistency across regions, accepting higher write latency.
Cassandra / ScyllaDB (multi-DC), DynamoDB Global Tables, Cosmos DBMulti-region, multi-writer NoSQL (LWW-style conflict resolution)Highly available writes everywhere, eventual consistency.
PostgreSQL / MySQL streaming replication, Aurora Global DatabaseSingle-writer primary with cross-region replicasActive-passive or home-region designs.
S3 Cross-Region Replication, GCS dual/multi-region bucketsObject replicationMedia durability across regions.
Kafka MirrorMaker 2, Confluent Cluster LinkingCross-region stream replicationGlobal event streams, DR for Kafka.
pgBackRest, WAL-G, AWS Backup, VeleroBackups, PITR, Kubernetes backup3-2-1 backups and restore automation.
Terraform, PulumiInfrastructure as codeRebuilding a region from scratch reproducibly.

16. Interview corner

How would you make Instagram survive the loss of an entire region?

Run active-active in at least three regions with ≤ 67% utilisation so two can carry full load. Stateless services everywhere behind a global load balancer/anycast edge with health-based traffic steering. Data: user DB shards with a home region (single writer) and async replicas in other regions; Cassandra with cross-region replication and LOCAL_QUORUM; object storage replicated cross-region; per-region rebuildable caches. On failure: drain the region at the edge, promote replicas for shards homed there with fencing of old primaries, shed low-priority load, move async jobs. RPO = replication lag (seconds); RTO = minutes. Prove it with regular region-drain drills, and keep separate PITR backups for logical corruption.

Define RPO and RTO and give appropriate values for Instagram's DMs, likes and analytics.

RPO = maximum tolerable data loss measured in time; RTO = maximum tolerable downtime. DMs: RPO seconds (or zero for messages acknowledged as sent, which might justify synchronous replication within a nearby region group), RTO minutes. Likes: RPO seconds-to-minutes is acceptable (counts can be recomputed from the likes table), RTO minutes (the app can hide counts meanwhile). Analytics: RPO hours (events can be replayed from Kafka/devices), RTO hours to a day.

Active-active with multiple writers: how do you handle two regions updating the same profile concurrently?

Best: avoid it — give each user a home region and route all their writes there, so there's a single writer per record. If multi-writer is required: last-writer-wins with hybrid logical clocks for simple fields (accepting lost concurrent updates), CRDTs for counters and sets (PN-counter for likes, OR-set for follows), version vectors with application merge for complex objects, and domain rules for security-sensitive data (e.g. "block wins over follow", "private wins over public").

What is a cell-based architecture and why use it in addition to multiple regions?

A cell is a complete independent stack serving a fixed subset of users, behind a thin router. Regions protect against regional disasters, but many outages are caused by deploys, poison requests or overload that hit all replicas of a service. Cells limit any such failure to ~1/N of users, enable progressive cell-by-cell deploys, and keep each cell at a tested maximum size. Trade-off: cross-cell data (social graph, feeds) needs separate handling, and the router becomes critical shared infrastructure that must be extremely simple.

Why isn't replication enough? What's your backup strategy?

Replication copies bad writes (bugs, malicious deletes, bad migrations) instantly to all replicas. Backups give point-in-time recovery. Strategy: 3-2-1 — continuous WAL archiving plus daily snapshots per shard to object storage in another region and account, with object lock for immutability; encryption with KMS keys; versioned media buckets; automated daily restore tests of random shards with integrity checks; tracked restore times against RTO; and deletion/retention policies that honour GDPR erasure.

Describe how you'd fail back after a region recovers.

Don't simply re-enable it. Treat the recovered region's databases as stale: rebuild them as replicas of the current primaries, and extract any writes that were committed there but never replicated (the RPO window) for reconciliation. Wait for lag ≈ 0, warm caches, then shift traffic gradually (1% → 10% → 50% → 100%) watching error rates, and move shard primaries back in batches during off-peak. Update the runbook with anything that surprised you.

17. Check your understanding

You have 4 active regions. What is the maximum safe normal utilisation per region to survive the loss of one region?

(N−1)/N = 3/4 = 75%. If one region fails, its 25% share is spread over the other three, each going from 75% to 100%. In practice you'd target a bit lower for safety margin.

Nightly backups run at 01:00. The database is corrupted by a bad script at 22:30 and you have no replicas or WAL archive. What is your effective RPO? How could you reduce it?

You must restore the 01:00 backup, losing 21.5 hours of data. Add continuous WAL archiving (point-in-time recovery, RPO of seconds), more frequent snapshots, and/or a delayed replica.

A user in Germany (home region EU) edits their bio, then opens their profile and sees the old bio. What is this anomaly and how would you fix it?

A read-your-writes violation: the read hit a replica (or cache) that hadn't yet received the write. Fixes: route the user's reads of their own data to the home primary for a short window after a write; or include a replication position token from the write and only read from replicas that have caught up; or update the cache synchronously on write.

Which DR strategy fits each: (a) internal HR reporting tool, (b) Instagram feed API, (c) a payments ledger requiring zero data loss?

(a) Backup & restore — hours of downtime are fine, cost matters. (b) Multi-site active-active — global users, minutes of downtime are costly. (c) Active-active or warm standby with synchronous/quorum replication across nearby regions (RPO = 0), accepting extra write latency.

During a failover you promote the EU replica to primary, but the old US primary comes back online 5 minutes later and starts accepting writes. What happened and how do you prevent it?

Split brain — two primaries accepting divergent writes. Prevent it with fencing: leases or epoch/term numbers checked by the storage layer, revoking credentials or network access of the old primary, and STONITH-style shutdown before promotion; clients and proxies should only route to the primary recorded in a consensus-backed directory.

Cross-region async replication lag is normally 300 ms but grows to 4 minutes during a write spike. Why does this matter for DR, and what would you do?

Lag is your current RPO: a region loss during the spike would lose ~4 minutes of writes. Alert on lag thresholds, add replication bandwidth/parallel apply, throttle non-critical bulk writes (backfills, migrations) to protect replication, and consider synchronous/quorum replication for the most critical data.

Does GDPR require that EU users' data never leaves the EU?

Not literally — GDPR restricts transfers outside the EEA unless a legal mechanism and adequate safeguards apply. But legal uncertainty (e.g. Schrems II, the large 2023 fine against Meta) pushes companies toward keeping EU personal data in EU regions, encrypting with in-region keys, and minimising what crosses borders.

🎯 Key takeaways

Related lessons