The write path: global strong consistency vs regional writes

What it is

The decision about where a write is authoritative, which is the decision every other multi-region choice follows from. Four shapes, and they are genuinely different systems rather than points on a tuning dial:

1. SINGLE-REGION WRITE, GLOBAL READ
   One region owns all writes; others serve reads from
   replicas.
   Write latency:  local for that region, cross-region for
                   everyone else (60 to 200 ms)
   Consistency:    strong at the writer, lagging elsewhere
   Failover:       promote a replica. Minutes, and it needs
                   rehearsing.

2. HOME-REGION PER ENTITY
   Each customer, tenant or key has a designated home region
   that owns its writes; other regions forward.
   Write latency:  local for users in their home region
                   (the large majority), cross-region for
                   the rest
   Consistency:    strong per entity, no conflicts by
                   construction
   Failover:       reassign homes. Per-entity, so it can be
                   partial.

3. GLOBAL STRONG CONSISTENCY
   Every write goes through consensus across regions.
   Write latency:  a cross-region quorum round trip on every
                   write, so 60 to 200 ms floor
   Consistency:    strict serializability
   Failover:       automatic, because the quorum already
                   spans regions.

4. ACTIVE-ACTIVE WITH ASYNC REPLICATION
   Every region accepts writes locally; conflicts resolved
   afterwards.
   Write latency:  local everywhere. Single-digit ms.
   Consistency:    eventual, with conflicts
   Failover:       nothing to fail over. Traffic just moves.

Commonly confused with the read path, which is a much easier problem: replicas everywhere, serve locally, accept staleness. The write path is where the difficulty is, and a design that treats "multi-region" as one decision has usually only solved reads.

The problem it solves

Physics. Cross-region round trips are 60 to 200 milliseconds and cannot be optimised: California to the Netherlands has a speed-of-light floor around 89 milliseconds and measures about 150, so we are within a factor of 1.7 of physics.

So a write must either:
  wait for a remote region        (60 to 200 ms per write)
  or not wait                     (and accept conflicts or
                                   a bounded loss window)

There is no third option, and every multi-region write
design is a way of arranging which writes pay and which
do not.

And the second constraint, which is the one that decides most real designs: what breaks if two regions write the same thing concurrently?

NOTHING BREAKS          session data, preferences, drafts,
                        counters, view counts
                        -> active-active is fine

SOMETHING IS LOST       a document edit, a profile change
                        -> tolerable with last-writer-wins,
                           and say so explicitly

AN INVARIANT BREAKS     a balance goes negative, two users
                        get the same username, inventory
                        oversells
                        -> active-active is NOT AVAILABLE
                           for this data. Not a tuning
                           question.

Mechanics

The latency arithmetic that decides it

Representative round trips:
  us-east-1 <-> us-west-2       ~60 ms
  us-east-1 <-> eu-west-1       ~75 ms
  us-east-1 <-> ap-southeast-1  ~220 ms
  eu-west-1 <-> ap-southeast-1  ~180 ms

A quorum write across 5 regions waits for the SECOND-slowest
of the four remote regions:
  from us-east-1:      ~75 ms
  from ap-southeast-1: ~180 ms

*** The same system has a 2.4x latency difference depending
    on which region the user is in. *** That asymmetry is a
    product property, not an implementation detail, and it
    should be surfaced deliberately rather than discovered.
Adding a commit wait, as Spanner does to absorb clock
uncertainty:
  + 2 x epsilon, historically single-digit milliseconds

So global strong consistency realistically costs 70 to 250 ms
per write. For a write-once-per-session workload that is
invisible. For a workload writing on every user action it is
the product.

The decision framework

Is there an invariant that breaks under concurrent writes?
  (uniqueness, monotonicity, a balance, inventory)
    YES -> that data cannot be active-active.
           Choose: global consensus (correct, slow) or
           home-region ownership (correct, fast for most
           users, forwards for the rest).
           *** Home-region ownership is the under-used
               answer and is usually the right one. ***

Is the write latency budget under ~50 ms?
    YES -> global consensus is out. Local writes with
           conflict resolution, or home-region ownership
           with users mostly in their home region.

Do users move between regions mid-session?
    YES -> home-region ownership needs session affinity or
           forwarding, and you need read-your-own-writes
           across the move. Version tokens.

Is this data genuinely conflict-free?
  (counters, sets, flags, presence, last-seen)
    YES -> CRDTs, active-active, and no coordination at all.

Is a bounded loss window acceptable on region failure?
    NO  -> writes must be acknowledged by a second region
           before returning, which is a 60 to 200 ms floor
           whether or not you call it consensus.

And the answer for a real system is almost always a mixture, which is the point worth making: one write path for the whole application is wrong in one direction or the other.

Home-region ownership: the under-used answer

It gets skipped because it sounds like single-region, and it is materially different.

Each entity (customer, tenant, account, workspace) has a
home region recorded in a small, globally-replicated
mapping.

  Write from a user in their home region:   LOCAL. ~2 ms.
  Write from a user elsewhere:              forwarded.
                                            60 to 200 ms.
  Read anywhere:                            local replica,
                                            with session
                                            tokens for
                                            read-your-writes.

Given ~85% of traffic is users in their home region, the
large majority of writes are local, and there is no
conflict resolution at all because each entity has ONE
writer.

The properties that make it attractive:

NO CONFLICTS, by construction. Not "resolved well": absent.
STRONG CONSISTENCY per entity, without consensus.
LOCAL LATENCY for the common case.
PARTIAL FAILOVER: a region failing means reassigning that
  region's entities, not failing over the whole system.
DATA RESIDENCY falls out for free: an EU customer's home is
  in the EU, and that is the compliance answer.

The costs, stated honestly:

- Cross-region writes are slow for users away from home,
  which is a real product experience for travellers and for
  genuinely multi-region customers.
- The home mapping is a globally-replicated dependency, and
  it must be cacheable and fail-static.
- Reassigning a home is a migration (drain, replicate,
  switch), so it is not instant.
- Entities that span homes (a shared document owned by users
  in two regions) need a rule, and "the owner's home wins"
  is usually it.

The failover story is the strongest argument: with global consensus, a region failure is handled automatically and every write already paid for it. With home-region ownership, a region failure means reassigning that region's entities, which is a real operation and affects only those entities. With single-region writes, a region failure is a full promotion that has to be rehearsed and frequently is not.

What global strong consistency actually buys

It is a legitimate choice and the reason to pick it is developer time rather than correctness alone.

WHAT YOU AVOID BY PAYING THE LATENCY
  conflict resolution logic, and the bugs in it
  reasoning about which invariants survive concurrency
  read-your-own-writes machinery
  the class of data-loss bugs that surface years later
  explaining eventual consistency to every new engineer

Spanner's own argument is essentially this: developer time
and correctness are worth more than the latency for a large
class of applications, and the 10 to 100 ms write cost is
acceptable for most workloads that are not write-per-
keystroke.

The workloads where it is clearly right: financial ledgers, inventory, anything where an invariant crossing entities must hold, and anything where the cost of a subtle consistency bug exceeds the cost of latency by a wide margin.

The workloads where it is clearly wrong: anything writing on every user interaction, anything latency-critical in a region far from the quorum, and anything where the data is genuinely conflict-free and the coordination buys nothing.

The failover question, which most designs under-specify

FOR EACH SHAPE, WHAT HAPPENS WHEN A REGION DIES?

single-region write   Promote a replica. The questions
                      nobody answers in advance: how much
                      lag was there (that is your data
                      loss), who decides, how long does it
                      take, and has it been rehearsed this
                      quarter?
                      *** Untested failover is not failover. ***

home-region           Reassign that region's entities to
                      another home. Per-entity, so it is
                      incremental and partial. Needs the
                      data to already be replicated there.

global consensus      Automatic. The quorum spans regions
                      and one region's loss leaves a
                      majority, IF you have at least three
                      regions. Two regions cannot form a
                      majority after losing one.

active-active         Traffic moves. Writes accepted during
                      the partition diverge and reconcile on
                      heal, and the divergence is bounded by
                      partition duration times write rate.

The "two regions cannot form a majority" point is worth stating, because a two-region consensus deployment is a common and broken design: losing either region loses quorum, so you have paid for consensus latency and bought no availability.

A worked example: splitting the write path

A SaaS product going multi-region: US and EU, planning APAC.

THE NAIVE PLAN
  "Active-active across all regions."

THE DATA AUDIT
  entity              concurrent write breaks?   volume
  ----------------------------------------------------------
  user session        no                          very high
  user preferences    loses an edit, tolerable    high
  documents           loses an edit, NOT
                      tolerable (hours of work)   high
  workspace members   uniqueness on email         low
  billing / invoices  balance invariant           low
  usage counters      no (CRDT)                   very high
  audit log           append-only, no conflict    high

THE RESULTING DESIGN
  session, counters, audit log
    -> active-active, local writes, CRDTs or append-only.
       No coordination.

  preferences
    -> active-active with last-writer-wins and hybrid
       logical clocks, and we DOCUMENT that a concurrent
       edit loses one.

  documents
    -> home-region ownership per workspace. Local for the
       ~85% of users in their workspace's region, forwarded
       otherwise. No conflicts, and it also solves EU data
       residency for free.

  workspace members, billing
    -> a small consensus group. These are low-volume, so
       the 75 ms write cost is invisible, and they are
       exactly the invariants that cannot be eventual.

THE OUTCOME
  Roughly 2% of writes pay a cross-region cost, and they are
  the ones where correctness is non-negotiable. Everything
  else is local.

  The naive plan would have been either 100% of writes at
  75 ms (if consensus everywhere) or a data-loss bug in
  documents and a duplicate-email bug in membership (if
  active-active everywhere).

The move that produced this is the data audit, and it takes an afternoon: for each entity, what breaks under concurrent writes, and how much volume is it. That table is the design.

Production evidence

Spanner (Corbett et al., OSDI 2012) provides global strict serializability using TrueTime, with a documented commit wait proportional to clock uncertainty, and its reported write latencies are the reference for what global consensus costs.

DynamoDB Global Tables uses last-writer-wins across regions and documents it explicitly, which is the honest version of active-active for data that tolerates it.

Cassandra's LOCAL_QUORUM with asynchronous cross-datacenter replication is the canonical local-writes-plus-async-replication shape, and its tunable per-query consistency level is the per-write durability idea in a shipped product.

CockroachDB's and YugabyteDB's geo-partitioning features are home-region ownership as a product feature: rows are pinned to a region by a partition column, so writes for that region's data are local. That both databases added it after starting with global consensus is evidence that the latency cost of consensus-everywhere is felt in practice.

Azure Cosmos DB's five consistency levels (strong, bounded staleness, session, consistent prefix, eventual) is the clearest commercial expression of the spectrum, and its documented latency and availability trade-offs per level are a useful reference.

AWS's guidance on multi-region architectures is explicit that a two-region consensus deployment cannot survive a region loss, which is the majority-quorum point.

The debate

The case for global strong consistency: correctness without reasoning about it, no conflict resolution code, no class of data-loss bugs surfacing years later, and no explaining eventual consistency to every new engineer. Spanner's argument is that developer time is worth more than latency, and for a large class of applications it is.

The case for active-active: local write latency everywhere, survives any region failure without a failover procedure, and scales without coordination. For session data, preferences, counters and feeds it is straightforwardly correct and anything else is over-paying.

The case for home-region ownership: local latency for the large majority of writes, no conflicts at all rather than conflicts resolved well, strong per-entity consistency without consensus, and data residency for free. The cost is slow writes for users away from home and a globally-replicated mapping.

My position: audit the data first, then use home-region ownership as the default for entity-scoped data, consensus for the small set with cross-entity invariants, and active-active for the genuinely conflict-free.

The data audit is the actual work and it takes an afternoon: per entity, what breaks under concurrent writes and how much volume it is. In the worked example it produced a design where 2 percent of writes pay a cross-region cost and they are exactly the ones where correctness is non-negotiable, against a naive plan that would have been either universally slow or contained a data-loss bug.

Home-region ownership is the answer I would push hardest, because it is consistently under-considered and it gets skipped for sounding like single-region. It gives no conflicts by construction rather than conflicts resolved well, which is a categorically different guarantee, and it makes region failover partial and per-entity rather than a full promotion that has to be rehearsed and usually is not.

The thing I would insist on naming is that when an invariant breaks under concurrent writes, active-active is not available for that data, and that is not a tuning question. Two regions can both accept the username "alice", and last-writer-wins picks one while the other user's account silently stops working. Balances go wrong by the amount of the discarded write. Teams reach for a better conflict resolver, and the answer is that the data needs a single writer.

And two-region consensus is a broken design that appears regularly: losing either region loses quorum, so you have paid the latency and bought no availability. Three regions minimum, or do not use consensus.

Where I would push back on the requirement: most teams asking for active-active want low read latency globally and low write latency locally, and do not actually need the same key writable in several regions. Home-region ownership with global read replicas delivers exactly that, and it is a much simpler system to operate and reason about. I would propose it first.

Follow-up Q&A

"How do you decide where writes happen?" By auditing the data, not by picking an architecture. For each entity: what breaks if two regions write it concurrently, and how much volume is it? Nothing breaks for sessions, counters and feeds, so those go active-active. Something is lost for preferences, so last-writer-wins with hybrid logical clocks, documented. An invariant breaks for balances, uniqueness and inventory, and for those active-active is not available at all. That table is the design, and it takes an afternoon.

"What does global strong consistency actually cost?" A cross-region quorum round trip per write, so 60 to 200 milliseconds depending on region, plus a commit wait if you are absorbing clock uncertainty. And there is an asymmetry worth surfacing: a five-region quorum from us-east waits about 75 milliseconds and from ap-southeast about 180, so the same system is 2.4 times slower for some users. That is a product property, not an implementation detail.

"What is home-region ownership and why do you like it?" Each entity, customer, tenant or workspace, has a designated home region that owns its writes, and other regions forward. Given roughly 85 percent of traffic is users in their home region, most writes are local at a few milliseconds, and there are no conflicts by construction because each entity has one writer. That is categorically different from resolving conflicts well. It also makes failover partial and per-entity rather than a full promotion, and data residency falls out for free.

"What are its costs?" Cross-region writes are genuinely slow for users away from home, which is a real experience for travellers and multi-region customers. The home mapping is a globally-replicated dependency that must be cacheable and fail-static. Reassigning a home is a migration rather than a config change. And entities spanning two homes, a document shared across regions, need a rule, which is usually that the owner's home wins.

"When is global consensus the right answer?" When there are cross-entity invariants, so financial ledgers, inventory, anything where a balance or a uniqueness constraint spans entities. And the argument for it is developer time as much as correctness: you avoid conflict resolution logic, the bugs in it, read-your-own-writes machinery, and the class of data-loss bugs that surface years later. For low-volume writes the 75 milliseconds is invisible, which is exactly the profile of the data that needs it.

"What happens when a region dies, under each shape?" Single-region writes need a replica promotion, and the questions nobody answers in advance are how much lag there was, which is your data loss, and whether it has been rehearsed this quarter. Home-region ownership reassigns that region's entities, which is partial and incremental. Global consensus is automatic if you have three or more regions. And active-active just moves traffic, with divergence bounded by partition duration times write rate.

"Why three regions rather than two for consensus?" Because two regions cannot form a majority after losing one, so a two-region consensus deployment pays the full cross-region latency on every write and buys no availability. It is a common design and it is broken. Three minimum, and I would ask what the third region is for if someone proposes two.

"A user travels from the EU to Singapore mid-session. What breaks?" Under home-region ownership their writes are now forwarded, so they are slower but correct. What needs handling is read-your-own-writes: reads served from the Singapore replica may not yet have their write, so the client carries a version token and the serving region either satisfies it, waits briefly, or reads from the home region. That is the mechanism that makes eventual consistency acceptable to actual users, and it is the piece most designs omit.

"Someone proposes active-active for everything. What do you say?" I would ask what happens when two regions concurrently write a balance, or both accept the username "alice", and let the answer make the case. Then I would say that most teams asking for active-active actually want low read latency globally and low write latency locally, which home-region ownership with global read replicas delivers with no conflict resolution at all and a much simpler system to operate. Active-active is right for genuinely conflict-free data, and it is the wrong default.

Common misconceptions

"Multi-region is one decision." Reads are easy: replicas everywhere, accept staleness. The write path is the difficulty, and a design that treats them together has usually only solved reads.

"A better conflict resolver fixes the invariant problem." If concurrent writes can break a uniqueness or balance invariant, that data needs a single writer. No resolver recovers a discarded write.

"Two regions is multi-region." For consensus it is not: losing either loses quorum. For active-active it is fine.

"Global consistency is too slow." It is 60 to 200 milliseconds on the writes that use it, and the data needing it is usually low-volume. Applying it to everything is what is too slow.

"Home-region ownership is just single-region." It is per-entity, so most writes are local, failover is partial, and residency falls out. That is a different system.

Interview delivery note

Separate reads from writes immediately, because conflating them is the common error: "Reads are the easy half: replicas everywhere, serve locally, accept staleness. The write path is where the difficulty is, and the question is where a write is authoritative."

Give the physics, because it closes off the optimisation conversation: "Cross-region round trips are sixty to two hundred milliseconds and that's within a factor of two of the speed of light, so it isn't an optimisation problem. A write either waits for a remote region or it doesn't, and every design is a way of arranging which writes pay."

Then make the audit the answer rather than an architecture: "So I'd audit the data before picking a shape. Per entity: what breaks under concurrent writes, and what volume is it? Nothing breaks for sessions and counters. Something's lost for preferences, which is tolerable if we document it. An invariant breaks for balances and uniqueness, and for those active-active isn't available at all, which is not a tuning question."

Push home-region ownership, because it is the under-considered answer: "And the shape I'd default to for entity-scoped data is home-region ownership: each workspace or tenant has a home region that owns its writes, others forward. Eighty-five percent of writes are local, there are no conflicts by construction rather than conflicts resolved well, failover is partial and per-entity, and EU data residency falls out for free."

Close with the worked outcome, because it makes the framework concrete: "In the case I worked that produced a design where about two percent of writes pay a cross-region cost, and they were exactly the ones where correctness was non-negotiable. The naive active-active-everywhere plan would have shipped a data-loss bug in documents and a duplicate-email bug in membership."

Further reading

  • Corbett et al., "Spanner: Google's Globally-Distributed Database" (OSDI 2012), for what global strong consistency costs and buys.
  • Azure Cosmos DB's consistency-levels documentation, for the clearest commercial statement of the spectrum and its trade-offs.
  • CockroachDB's and YugabyteDB's geo-partitioning documentation, for home-region ownership as a shipped feature.
  • DynamoDB Global Tables and Cassandra multi-datacenter documentation, for two production systems making opposite simplicity trades.
  • Design a multi-region active-active KV store, for the conflict-resolution mechanics this page deliberately does not repeat.