Expert Track · Phase J · 6 of 26
Physics has a floor. Every cross-region round-trip in your protocol costs 60-200ms. The engineering task is minimizing round-trips while preserving strong consistency.
Module 52 · Expert 6 / 26 · 95 min

Geo-distributed
transactions.

The specific engineering for cross-region distributed transactions at continental scale. Spanner\'s TrueTime + commit-wait (2012), CockroachDB\'s HLC + NTP alternatives (2014), follower reads with bounded staleness, and locality-aware data placement — the specific techniques that make sub-100ms external consistency achievable at global scale. Where M.51 taught the protocols, M.52 teaches the geography.

// What you'll know by the end

  • Speed-of-light floors between regions
  • TrueTime and commit-wait mechanics
  • Regional, global, and per-row placement
  • Follower reads with staleness bounds
§ 01 — Physics has a floor

Speed of light gives
you 5ms per 1000km.
Every RTT is a
fixed tax.

The speed of light in fiber optic cable is about 200,000 km/s — approximately 2/3 the speed of light in vacuum, due to the refractive index of glass. This gives you a specific and hard floor: light takes about 5ms to travel 1000km one-way in fiber. Round-trip: 10ms per 1000km. NYC to London is 5560km — the physical floor for RTT is 56ms; actual production RTT (with routing overhead, queuing, and processing) is 70-100ms. NYC to Tokyo is 10,900km — physical floor is 109ms; actual is 130-180ms. Sydney to London is 17,000km — physical floor is 170ms; actual is 220-300ms. These numbers are physical constants — no amount of engineering can violate them. Every cross-region round-trip in your distributed transaction protocol pays this cost. If your protocol requires 3 round-trips per transaction, cross-region transactions take at least 3× the RTT, plus processing time. This is the specific reason geo-distributed transaction engineering exists as a distinct discipline: you cannot design protocols that assume "the network is fast" when the network is bounded by the speed of light across continents.

// SPEED OF LIGHT · RTT BETWEEN MAJOR REGIONS · THE PHYSICS FLOOR
CROSS-REGION RTT · PHYSICAL FLOOR + ACTUAL PRODUCTION LATENCY SF us-west NYC us-east LON eu-west TYO ap-northeast SYD ap-southeast ~65ms 4100km · floor 41ms ~76ms 5560km · floor 56ms ~230ms 9600km · floor 96ms ~110ms 7800km · floor 78ms // TRANSACTION LATENCY BUDGET · N ROUND-TRIPS × RTT Protocol RTTs NYC↔LON (76ms) SF↔TYO (~100ms) LON↔SYD (~300ms) Classical 2PC (2 RTT) 152ms 200ms 600ms Spanner-style (1 RTT + cw) 83ms 107ms 307ms Local read (0 cross-region) <1ms <1ms <1ms Follower read (bounded stale) <1ms <1ms <1ms // Cross-region protocols pay RTT × #round-trips. Local reads pay nothing. Placement is the specific engineering.
The physics budget. Speed of light in fiber = ~200,000 km/s. Physical floor per 1000km = 5ms one-way, 10ms RTT. Actual production RTTs are 20-50% higher due to routing, queuing, and switching overhead. NYC↔London is 5560km — physical floor 56ms, actual ~76ms. SF↔Tokyo is ~9000km — floor 90ms, actual ~100ms. London↔Sydney is 17,000km — floor 170ms, actual ~300ms. The transaction latency budget is the product of protocol round-trips × RTT. Classical 2PC requires 2 RTTs per transaction — cross-region cost is 150-600ms. Spanner-style with commit-wait requires 1 RTT + commit-wait — cost is 80-300ms. Local reads and follower reads with bounded staleness cost less than 1ms because they touch only local replicas. The specific engineering discipline: place data such that most transactions are local, use Spanner-style protocols for the necessary cross-region transactions, and use follower reads for read-heavy workloads that can tolerate bounded staleness. This is what M.52 is about.

The specific engineering task isn\'t to make cross-region round-trips faster (impossible — bounded by physics) but to minimize the number of cross-region round-trips per operation. This is where the engineering leverage exists. Techniques: (a) data placement — put data close to where it\'s used, so most transactions touch only local replicas; (b) protocol design — Spanner\'s commit-wait mechanism eliminates one round-trip vs classical 2PC by using bounded-uncertainty clocks; (c) read strategies — follower reads with bounded staleness serve reads from local replicas without cross-region round-trips; (d) quorum placement — configure Paxos replica placement across regions to minimize the number of regions any quorum must cross; (e) batching — group multiple operations into single cross-region round-trips where possible. Each technique has a specific cost model and applies to a specific class of workload. Understanding when each applies is the specific Expert-tier competence this module builds.

// FOUR APPROACHES TO GEO-DISTRIBUTED DATA · WHERE EACH FAILS OR FITS
Attempt 1: single-region deployment// ignore geography · deploy in one datacenter
"Just deploy in one region. Users worldwide connect over the internet. Simple architecture." Works for small-scale or region-specific services (a bank operating only in the US, a European government agency serving only Europe). Fails specifically when: (a) users are globally distributed and latency to the deployment region is unacceptable — a user in Sydney hitting a US-east deployment pays ~220ms RTT for every request, kills UX; (b) regulatory requirements mandate data locality (GDPR in Europe, data residency in China, etc.) — single-region deployment violates these; (c) datacenter failure takes down the entire service — no geo-redundancy for disaster recovery. Not wrong for narrow use cases; wrong for globally-distributed users.// FAIL MODE: global user latency · no geo-redundancy · regulatory
SIMPLE
BUT LIMITED
Attempt 2: naive multi-region synchronous// every write hits every region sync · consensus across regions
"Deploy in 3 regions with synchronous replication for consistency. Every write coordinates across all regions." Provides strong consistency and geo-redundancy but pays the full cross-region RTT for every write. Cross-region synchronous consensus (Paxos with replicas in 3 regions) requires waiting for a majority of replicas to acknowledge — if regions are NYC/LON/TYO, majority = 2 of 3, latency = max(NYC↔LON, NYC↔TYO) = ~200ms per write. Throughput drops precipitously; UX degrades for write-heavy workloads. Also: if the leader is in NYC, users in LON and TYO pay the full round-trip to NYC for every write. This is the naive multi-region deployment that doesn\'t work at scale — the physics floor eats you alive.// FAIL MODE: every write = cross-region RTT · unusable latency
UNUSABLE
LATENCY
Attempt 3: async multi-region// eventual consistency across regions · local writes only
"Deploy in multiple regions with async replication between them. Each region serves local reads and writes; changes propagate asynchronously." Solves the latency problem but sacrifices consistency. Each region is essentially its own database with async replication as backup. Common problems: (a) write conflicts — same key written in two regions must be reconciled somehow; (b) stale reads — a user in LON writes, then reads from TYO before replication catches up, sees old value; (c) no external consistency — regulatory and audit requirements often mandate global ordering that async replication can\'t provide; (d) split-brain during partition — divergent writes accumulate on both sides, hard to reconcile. Fine for eventually-consistent workloads (social feeds, product catalogs). Wrong for anything requiring strong consistency (money, inventory, ordering-sensitive ops).// FAIL MODE: no strong consistency · conflicts · stale reads
LATENCY OK
NO CONS.
Attempt 4: Spanner-style + locality-aware placement// TrueTime + follower reads + data placement · the modern approach
"Use Spanner-style protocols (2PC over Paxos), place data such that most transactions are local, use bounded-uncertainty clocks (TrueTime or HLC) for external consistency, and serve reads from local replicas via follower reads." Solves the physics problem through specific techniques: (a) most transactions are local — data placement ensures typical workloads touch only local replicas, single-digit ms latency; (b) the cross-region transactions that do happen use Spanner-style — 2PC over Paxos with TrueTime commit-wait, 1 RTT + commit-wait ≈ 80-200ms, acceptable for occasional cross-region ops; (c) reads use follower reads — local replicas serve most reads with bounded staleness (typically 5-30 seconds), sub-millisecond latency; (d) writes to non-local data use leaseholder proxies — the leaseholder (or leader) handles cross-region coordination, client pays only one cross-region RTT; (e) external consistency is preserved via bounded clocks — TrueTime or HLC gives you globally-consistent ordering without additional round-trips. This is the specific engineering that makes global-scale strong-consistency practical. Used by Spanner, CockroachDB, YugabyteDB, TiDB with placement rules.// FIT: locality-aware placement · Spanner-style + follower reads
EXPERT
PATTERN
// THE COMPOSITE PATTERN

Each earlier attempt fails specifically. Single-region can\'t serve global users. Naive multi-region sync pays cross-region RTT on every write. Async multi-region loses consistency. The Expert pattern combines four specific techniques: (a) locality-aware data placement to make most transactions local; (b) Spanner-style 2PC-over-Paxos for the necessary cross-region transactions; (c) bounded-uncertainty clocks (TrueTime or HLC) for external consistency without extra round-trips; (d) follower reads for read-heavy workloads with bounded staleness. This is what modern globally-distributed databases (Spanner, CockroachDB, YugabyteDB) provide. Understanding how to configure each piece for your specific workload is the M.52 competence. §02 walks through the physics and TrueTime deeply; §03 walks through the three placement patterns.

The historical arc of geo-distributed transactions is specifically about solving the cross-region latency problem while preserving strong consistency. Before 2012: geo-distribution meant giving up consistency. Eventually consistent multi-region deployments (Dynamo, Cassandra) were the only practical option — strong consistency across regions was considered impractical due to physics. 2012: Google publishes Spanner. The specific innovation is TrueTime — GPS-clock plus atomic-clock synchronization across all Google datacenters, giving bounded clock uncertainty of ±1-7ms. Combined with a specific commit-wait mechanism (wait out clock uncertainty at commit rather than requiring additional round-trips), this enables external consistency at global scale. Spanner is the specific proof-point that strong-consistency multi-region OLTP is feasible. 2014-2015: CockroachDB releases with HLC-based approach. Recognizing that most teams don\'t have GPS/atomic clocks in every datacenter, CockroachDB uses HLCs (Hybrid Logical Clocks — see M.49) with NTP-synchronized wall-clocks. Provides weaker guarantees than TrueTime (no bounded uncertainty) but adequate for many workloads with careful protocol design. Becomes the reference open-source Spanner-alike. 2015-2017: YugabyteDB, TiDB with placement rules emerge. Various open-source and commercial distributed SQL databases adopt Spanner-style or Percolator-style patterns, each with specific placement configuration APIs. 2018-2020: Follower reads become standard. The recognition that reads dominate writes in most workloads (100:1 or higher ratio) means read latency optimization is high-leverage. Follower reads with bounded staleness — reads served from any replica within a specific staleness bound — become a standard feature. 2020+: Sub-100ms external consistency at global scale is achievable and standardized. Modern deployments target and achieve this. The specific engineering techniques are documented, tools support them, and senior engineers are expected to design for this. The arc explains why "geo-distribution requires eventual consistency" turned into "geo-distribution requires specific protocol + placement + read-strategy engineering, and here\'s how to do it correctly".

Speed of light is 5ms per 1000km one-way, and no protocol can violate it. The engineering task is minimizing round-trips through placement, commit-wait, and follower reads.
§ 02 — TrueTime and commit-wait · Spanner\'s specific insight

Bounded uncertainty.
Wait it out at
commit. One RTT.

Spanner\'s specific and famous innovation is TrueTime, a globally-synchronized clock service with bounded uncertainty. Every Google datacenter has GPS receivers (getting time from GPS satellites\' atomic clocks) plus locally-hosted atomic clocks (in case GPS is unavailable). TrueTime exposes a specific API: TT.now() returns an interval [earliest, latest] such that the true current time is guaranteed to be within that interval. Typical uncertainty (latest - earliest) is 1-7ms depending on clock health. This bounded-uncertainty guarantee is what enables Spanner\'s specific external consistency protocol — the commit-wait mechanism eliminates one round-trip compared to classical 2PC while providing globally-consistent external ordering. Understanding TrueTime and commit-wait precisely is the specific competence that turns "Spanner is magic" into "Spanner does one specific thing with bounded clocks, and here\'s exactly what."

// TRUETIME + COMMIT-WAIT · THE SPECIFIC MECHANISM FOR EXTERNAL CONSISTENCY

TRUETIME · TT.now() = [earliest, latest] · COMMIT-WAIT AT COMMIT t=0 real time → TT.now() at t=100ms: [97, 103]ms earliest latest ← uncertainty = 6ms 97 103 CLIENT: write(x=42) COORDINATOR: 2PC prepare + Paxos commit_ts = 103 COMMIT-WAIT (6ms) ✓ ACK client // COMMIT-WAIT MECHANICS 1. Coordinator picks commit_ts = TT.now().latest (= 103ms) — guaranteed to be in future. 2. Wait until TT.now().earliest > commit_ts (= 103ms) — real time has caught up. 3. Now safe to acknowledge client — any observer with TT clock will see this txn as past. Result: external consistency (real-time ordering) without extra round-trips. Cost: commit-wait ≈ uncertainty ≈ 5-10ms.
TrueTime + commit-wait. Spanner\'s specific mechanism for external consistency. When a transaction commits, coordinator picks commit_ts = TT.now().latest — a timestamp guaranteed to be in the future (because the true current time is somewhere in the uncertainty interval, and latest is the upper bound). Then coordinator waits until TT.now().earliest > commit_ts — meaning real wall-clock time has definitely passed commit_ts on all clocks in the system. Only then does it acknowledge the client. The guarantee this provides: any subsequent observer (anywhere in the world) whose TrueTime says "now" is greater than commit_ts will see this transaction as past. This is external consistency — global ordering matching wall-clock time — achieved without additional round-trips. Cost: the commit-wait duration, typically 5-10ms (equal to the clock uncertainty). Alternative approaches (classical 2PC) would require additional round-trips to achieve the same guarantee. Spanner\'s specific insight: pay commit-wait time instead of round-trip time; commit-wait is bounded by clock uncertainty (~7ms), round-trip is bounded by physics (~100ms cross-continent).
i
TrueTime API.

TT.now() returns [earliest, latest], where true time is guaranteed within the interval. TT.after(t) returns true if t < earliest. TT.before(t) returns true if t > latest. This bounded-uncertainty API is what makes Spanner\'s protocol possible — code can reason about "definitely past" and "definitely future" with mathematical certainty.

ii
Physical implementation.

GPS receivers in every datacenter provide time from GPS satellites\' atomic clocks. Local atomic clocks (rubidium or cesium) as backup and cross-check. Time daemons synchronize local clocks to these references. Typical uncertainty: ±1-4ms during healthy operation; ±7-10ms during clock daemon transitions. Spanner monitors uncertainty and refuses to commit if it exceeds thresholds.

iii
Commit-wait mechanics.

At commit: coordinator picks commit_ts = TT.now().latest. Then waits until TT.now().earliest > commit_ts. Only then acknowledges client. This ensures any subsequent transaction (anywhere) with a later start_ts will see this transaction as committed. Cost: commit-wait duration = clock uncertainty ≈ 5-10ms.

iv
Why it beats classical 2PC.

Classical 2PC requires 2 round-trips (prepare + commit) for cross-region atomicity. Spanner uses 2PC over Paxos (M.51) so state is replicated, plus TrueTime commit-wait to establish external consistency. Net: 1 round-trip + commit-wait vs 2 round-trips. Savings: one RTT (~50-150ms cross-region) at cost of ~5-10ms commit-wait. Huge win.

v
CockroachDB HLC alternative.

Most teams don\'t have GPS/atomic clocks. CockroachDB uses HLC + NTP with maximum clock offset assumptions (typically 500ms). When a transaction reads a value with timestamp within uncertainty window, it either retries with a new timestamp or waits. Provides weaker guarantees than TrueTime but adequate for many workloads. Trades commit-wait for occasional read retries.

vi
Why external consistency matters.

External consistency = the transaction order matches real wall-clock time. Required for: audit trails ("who did what when"), regulatory compliance (financial systems must order events by real time), user experience ("I did A, then B — I should see B after A"). Weaker forms (serializability without real-time) allow ordering that violates wall-clock, which produces subtle bugs and audit failures.

The commit-wait mechanic (iii) is Spanner\'s specific and elegant insight for achieving external consistency without additional round-trips. The intuition: to prove that transaction T1 committed before transaction T2 started (external consistency), we need some observable event that\'s definitely after T1\'s commit and definitely before T2\'s start. Classical 2PC achieves this by requiring T1\'s commit acknowledgment to happen before T2 can start — but if T2\'s client is in a different region, this requires the acknowledgment message to travel from T1\'s coordinator to T2\'s client to T2\'s coordinator, which is 2 cross-region round-trips. Spanner\'s alternative: coordinator picks commit_ts to be in the "definitely future" (using TT.now().latest), then waits until the commit_ts is in the "definitely past" (using TT.now().earliest). Once commit-wait completes, any observer\'s TrueTime clock will read a time greater than commit_ts, so their transactions will get later start_ts values, so they\'ll see T1 as committed. The insight: use bounded clock uncertainty as the "medium" for ordering rather than message round-trips. Cost: commit-wait duration = ~clock uncertainty ≈ 5-10ms. Vs classical 2PC\'s cross-region round-trip of 60-200ms, this is a 10-40× improvement. Spanner\'s entire performance profile at global scale rests on this specific insight.

The CockroachDB HLC alternative (v) is the specific approach for teams without GPS/atomic clock infrastructure. Recognizing that TrueTime requires expensive hardware, CockroachDB uses HLCs (M.49) — logical clocks combined with NTP-synchronized wall-clocks. The specific tradeoff: no bounded uncertainty guarantee, so occasional reads may hit values within the "uncertainty window" (values written after the reader\'s HLC started but with earlier wall-clock timestamps due to clock skew). CockroachDB handles this specifically: (a) reads track their HLC "read timestamp"; (b) when reading a value with wall-clock timestamp within [read_ts - max_offset, read_ts], the read must either retry with a higher timestamp or wait; (c) the retry usually succeeds because subsequent reads see the value with a stable timestamp. Cost: occasional read retries (typically <1% of reads) instead of commit-wait on every write. Different tradeoff profile but similar net result — external consistency for most workloads at reasonable cost. Real production CockroachDB deployments typically see 5-10ms average read latency including the retry cost, competitive with Spanner\'s numbers. YugabyteDB uses a similar approach. TiDB\'s TSO approach is different — instead of distributed clocks, use a centralized Timestamp Oracle that provides globally-monotonic timestamps (introducing a specific TSO scaling concern that Percolator-style deployments must handle).

The external consistency requirement (vi) is what distinguishes Spanner from "just serializable" databases. Serializability (M.50) requires that transactions be equivalent to some serial order — but that serial order doesn\'t need to match wall-clock time. External consistency adds: the serial order must respect real-time ordering of non-overlapping transactions. This matters specifically for: (a) audit trails — regulatory compliance in financial systems requires event ordering to match real time; if T1 happened before T2 in wall-clock time, the audit log must reflect this; (b) read-after-write guarantees — a user who writes X and then reads X must see the write, regardless of which replica serves the read; (c) cross-session ordering — user A completes T1, tells user B about it via out-of-band communication, user B\'s subsequent read must see T1. Spanner provides all these via TrueTime + commit-wait. Serializable-but-not-externally-consistent databases (like classical MySQL with async replication) have specific gaps here — the "hallway phone problem" (M.50) manifests as observable stale reads across sessions. Modern global-scale deployments increasingly require external consistency because regulatory and UX requirements demand it, and Spanner-style protocols make it achievable at reasonable cost. Understanding this distinction is the specific Expert-tier competence for global deployment architecture.

TrueTime\'s bounded uncertainty is the medium. Commit-wait pays a small tax to establish external consistency without cross-region round-trips. One RTT + 7ms beats 2 RTT every time.
§ 03 — Three placement patterns · regional, global, per-row

Data placement is
the specific
engineering. Latency
follows.

Given the protocols (M.51) and the physics (§01, §02), the highest-leverage engineering choice for geo-distribution is data placement. Place data where it\'s used, and most transactions are local. Place data everywhere, and most reads are local but every write pays cross-region. Place data per-row based on ownership, and each row is optimized independently. Modern distributed databases (Spanner, CockroachDB, YugabyteDB) provide specific placement APIs — regional tables, global tables, regional-by-row — that let you make this choice per-table or per-row. Understanding when each fits which workload is the specific competence M.52 builds.

// THREE PLACEMENT PATTERNS · REGIONAL · GLOBAL · REGIONAL-BY-ROW

THREE PLACEMENT PATTERNS · WHERE DATA LIVES · WHERE LATENCY COMES FROM REGIONAL TABLE "data lives in one region" US-E ◼◼◼ EU ··· AP ··· LATENCY PROFILE: Local (US-E) reads: <1ms Local (US-E) writes: 5-10ms Cross-region reads: 60-150ms Cross-region writes: 60-150ms USE CASES: User\'s home-region data Regulatory-bounded data Region-specific catalogs PROS: cheap, simple CONS: remote users slow CRDB REGIONAL BY TABLE GLOBAL TABLE "replicated to all regions" US-E ◼◼◼ EU ◼◼◼ AP ◼◼◼ LATENCY PROFILE: Local reads (any region): <1ms Writes: 100-300ms Every write hits all regions via consensus quorum USE CASES: Product catalogs (rarely written) Reference data (currencies, tax) Read-mostly configuration PROS: fast reads global CONS: slow writes global CRDB GLOBAL TABLE REGIONAL-BY-ROW "each row has a home region" US-E ◼◻◻ EU ◻◼◻ AP ◻◻◼ LATENCY PROFILE: Home-region ops: 5-10ms Cross-region ops: 60-150ms Each row optimized separately Requires locality hint per row USE CASES: User data by user\'s home region Multi-tenant with tenant region Data residency compliance PROS: flexible per-row CONS: schema complexity CRDB REGIONAL BY ROW
Three placement patterns side by side. Regional table: all data lives in one primary region. Local operations are fast (5-10ms writes, sub-ms reads); cross-region operations pay full RTT (60-150ms). Best for region-specific data — European customer records for a European bank, user\'s home-region trading account. Global table: data is replicated to all regions via consensus. Reads are fast everywhere (sub-ms, served from local replica via follower reads); writes are slow everywhere (100-300ms, must reach quorum spanning regions). Best for rarely-written reference data — product catalogs, currency conversion rates, tax tables. Regional-by-row: each row has a designated "home region" specified via a hint column. Rows are stored in their home region; access from home region is fast, cross-region is slow. Best for multi-tenant workloads where each tenant has a home region, or user data where each user has a home region. Requires application-level locality hints in the schema. All three patterns are supported by modern distributed SQL databases (CockroachDB, YugabyteDB, TiDB) with specific per-table or per-row placement configuration.
i
Regional tables.

All data lives in one region with multi-zone replication within that region for durability. Local ops fast (5-10ms); remote ops pay full cross-region RTT. Best for data that has a natural regional home — European bank\'s European accounts, US trading firm\'s US positions. Regulatory data residency requirements often mandate this pattern.

ii
Global tables.

Data replicated to all regions via consensus. Reads served from local replica everywhere; writes pay full cross-region latency to reach quorum. Best for read-mostly reference data (rarely written, frequently read from all regions) — product catalogs, currency rates, feature flags. CockroachDB\'s GLOBAL tables and YugabyteDB\'s equivalent implement this pattern.

iii
Regional-by-row.

Each row has a "home region" specified via a locality column. Rows physically stored in their home region\'s replicas. Access from home region is fast; cross-region is slow. Best for multi-tenant SaaS where each tenant has a region, or per-user data where each user has a region. Schema requires a locality hint column (e.g., region STRING NOT NULL) used by database routing.

iv
Follower reads.

Serve reads from any replica, not just the leader. Cost: reads may be slightly stale (5-30 seconds typically). Benefit: reads are fast everywhere without cross-region round-trips. Standard for read-heavy workloads that tolerate bounded staleness. CockroachDB\'s AS OF SYSTEM TIME and Spanner\'s bounded staleness reads implement this.

v
Leaseholder placement.

Even within regional tables, the specific replica that serves writes (leaseholder or leader) matters. Placing leaseholders in the region with highest write traffic minimizes latency for that region\'s writes. CockroachDB\'s LEASE PREFERENCES setting; Spanner\'s zone-aware placement. Fine-grained control for write latency optimization.

vi
Mix patterns per table.

Real deployments use different patterns for different tables. User profiles: regional-by-row (each user in their home region). Product catalog: global (read everywhere, rarely written). Orders: regional (each order in the region where it was placed). Reference data: global. This mixed approach is what "locality-aware architecture" actually looks like.

The regional table pattern (i) is the specific choice for data with a natural regional home. Consider a global bank: European customer accounts (subject to GDPR data residency) live in EU regions; American accounts live in US regions; Asian accounts live in AP regions. Local transactions on local accounts are fast (5-10ms) because all data is local. Cross-region transactions (an American customer transferring to a European account) are slower (60-150ms) because they cross regions. This is fine because cross-region transactions are rare — most customers primarily transact in their home region. The specific engineering: (a) partition data by geography such that the partition key encodes the region (e.g., customer_id includes region prefix); (b) use CockroachDB REGIONAL BY TABLE or Spanner named-zone placement to pin the table to specific regions; (c) route application requests to the region matching the data (or accept remote-region access with higher latency); (d) monitor cross-region transaction rate — if it climbs above 10-20%, reconsider partitioning strategy. This pattern is the default for regulatory-bound data and geographically-distinct business operations.

The global table pattern (ii) is the specific choice for read-mostly reference data. Consider a product catalog: 100 million products, updated a few times per day by merchandisers, queried billions of times per day by shoppers. Reads are dominant by 100,000× or more. Global tables optimize for read latency: replicas everywhere, reads served from local replica. Write latency is bad (100-300ms) but writes are rare, so aggregate cost is low. The specific engineering: (a) identify tables where read/write ratio is >1000:1 and read latency matters more than write latency; (b) use CockroachDB GLOBAL or equivalent; (c) accept that writers pay full cross-region latency and design write workflows accordingly (batch updates during maintenance windows if possible); (d) use follower reads for even lower latency where bounded staleness is acceptable. Real-world examples: product catalogs (Amazon, Shopify), currency exchange rates, tax tables, feature flags, static configuration. Anti-example: user session state — high write rate, latency-sensitive writes; regional-by-row or regional table is better.

The regional-by-row pattern (iii) is the specific choice for data with per-record ownership. Consider a global SaaS platform: 10,000 tenants, each based in one region. Tenant A\'s data (all rows with tenant_id = A) should live in tenant A\'s region. Tenant B\'s data lives in tenant B\'s region. Regional-by-row provides this: each row has a locality hint column (typically an ENUM of region values), and the database\'s partitioning uses this to place rows. Access from the tenant\'s region is fast; cross-region access (rare — support engineers querying for troubleshooting) is slower. The specific engineering: (a) add a locality column to every table (typically region crdb_internal_region NOT NULL); (b) partition on this column; (c) configure REGIONAL BY ROW placement; (d) route application requests to the region matching the tenant. Real examples: multi-tenant SaaS (Salesforce, GitHub Enterprise), per-user data at global scale (WhatsApp, Slack). This pattern requires schema changes and application-level locality awareness but provides the best latency for per-row-owned data.

Regional keeps data where it\'s used. Global replicates to every region for fast reads. Regional-by-row picks a home region per record. Real deployments mix all three per table.
§ 04 — Geo-placement explorer

Three placements.
Three workloads.

Below: each of three placement patterns (Regional · Global · Regional-by-row) evaluated against three workload profiles (Local writes · Cross-region reads · Cross-region writes). Watch how each placement fits or fails each workload — the sharp diagonals show exactly which placement suits which workload, and the off-diagonals show the specific latency costs. This is the matrix Expert engineers implicitly consult when placing each table in a globally-distributed database.

GEO.SIM // m.52 lab
Workload →
// GEO-PLACEMENT BEHAVIOR · under current workload
// METRICS · LATENCY / CONSISTENCY PROFILE
Read latency-
Write latency-
Consistency-
Availability-
Cost profile-
Overall fit-
// VERDICT
Loading...
...
§ 05 — Where geo-placement decays

Every geo latency
bug is a placement
mismatch.

The failure modes of geo-distributed deployments are the specific mechanisms by which "our globally-distributed database" turns into "cross-region latency is killing us" or "our compliance audit failed because data crossed borders." Each of these anti-patterns is a real production pattern with a specific mitigation that Expert engineers deploy by default. Recognizing them at architecture time saves the migration.

// FIVE GEO-DISTRIBUTION ANTI-PATTERNS

i
The everything global
"We deployed all our tables as GLOBAL tables for ‘maximum flexibility.\rsquo; Now every write pays 250ms cross-region latency. Our user login (which writes a session record) takes half a second. Users think the site is broken."

Applying global-table placement to write-heavy tables produces catastrophic write latency. Global tables replicate writes to all regions via consensus, which requires the full cross-region RTT. For read-mostly reference data this is fine (writes are rare); for write-heavy operational data (sessions, user actions, orders) it\'s a disaster. Every write pays the physics floor. The fix: (a) identify tables by read/write ratio; (b) apply GLOBAL only to tables with >1000:1 read/write ratio (catalogs, config, reference data); (c) use REGIONAL for user-owned data (regional-by-row or single-region); (d) use follower reads for latency-optimized reads of regional tables; (e) design write paths to avoid cross-region writes whenever possible. The general principle: GLOBAL placement is a specific pattern for a specific read-mostly workload, not a default choice.

ii
The ignored data residency
"Our multi-region CockroachDB deployment placed European users\' data in US regions because that\'s where our replica quorum resolved. GDPR audit flagged us; we had to rebuild the deployment to comply with EU data residency. Cost us a quarter of engineering time."

Distributed databases don\'t enforce data residency by default — they optimize for consistency and availability. Without explicit locality configuration, data may end up in any region where replicas exist. Regulatory frameworks (GDPR in Europe, PIPL in China, various national laws) mandate that specific categories of data (personal data, financial data, government-related data) stay within specific jurisdictions. Violation costs: fines (up to 4% of global revenue under GDPR), forced data migration, reputation damage. The fix: (a) audit which data categories require residency at architecture time (before deployment); (b) use REGIONAL BY ROW with locality columns that map to compliance regions; (c) configure LEASE PREFERENCES to keep leaseholders in the correct regions; (d) use zone-aware replica placement to ensure quorum-holding replicas are all in the compliance region; (e) periodically audit actual data placement (some databases provide placement observability tools). The general principle: data residency compliance requires explicit locality configuration; it\'s never automatic.

iii
The naive multi-region sync
"We wanted ‘strong consistency\rsquo; so we set up synchronous replication across 3 regions (NYC/LON/TYO) with a 3-way quorum. Every write requires 2 of 3 regions to ack, which means at least 100ms latency including a trans-Pacific hop. Peak write throughput is 200/sec. We serve 10K requests/sec on the frontend."

Synchronous cross-region replication with quorum spanning distant regions produces write latency equal to the RTT to the furthest region in the quorum. A 3-region deployment with a 2-of-3 quorum where regions are geographically distant (NYC/LON/TYO) requires the write to travel to at least the median-latency region. Throughput ceiling is proportional to 1/write_latency per lock — with 100ms latency, hundreds of writes per second per lock, orders of magnitude below application demand. The fix: (a) place replicas within a single region for local durability, use async cross-region replication for DR; (b) use 5 replicas across 3 regions with locality-aware placement so majority of replicas are typically local; (c) accept that cross-region writes are the rare exception, not the common case; (d) partition data such that most writes stay within one region; (e) consider Spanner-style with TrueTime to reduce cross-region round-trip count. The general principle: quorum placement determines write latency; place replicas such that typical writes reach quorum within one region.

iv
The unbounded follower read staleness
"We enabled follower reads to reduce cross-region read latency. Users occasionally see very stale data (minutes old) because our follower read staleness is unbounded. A user updates their profile, refreshes the page, sees old data for 3 minutes. Support tickets pile up."

Follower reads without a bounded staleness parameter can return data arbitrarily old, breaking read-your-writes semantics and confusing users. Follower replicas may fall behind due to replication lag, network issues, or heavy load on the follower. Without bounds, reads can be minutes or hours stale. The fix: (a) always specify a staleness bound (e.g., CockroachDB\'s AS OF SYSTEM TIME follower_read_timestamp() targets ~4.8s staleness by default, tunable); (b) add read-your-writes guarantees at the application layer using session tokens or version numbers; (c) route user\'s own reads to leader/leaseholder for read-your-writes, use follower reads for reads of other users\' data; (d) monitor replication lag and alert when it exceeds thresholds; (e) consider bounded staleness (Spanner\'s "bounded staleness" reads with explicit bound). The general principle: follower reads are a specific latency optimization with a specific staleness cost; bound the staleness explicitly and design read paths accordingly.

v
The hot leaseholder in wrong region
"Our regional table for orders is placed in US-East. But 80% of our orders come from Europe (unexpected growth). Every European order write goes to US-East, paying 76ms cross-region RTT. Order throughput is bottlenecked; European users complain about slow checkout."

Leaseholder placement matters even within regional configurations — if the write leaseholder is in a region far from the primary write source, every write pays cross-region latency. Regional tables place data in specific regions, but the leaseholder (the replica that serves writes) can be in a different zone or region within that placement. If most writes come from a different region than the leaseholder, latency is high. The fix: (a) monitor which region generates most write traffic; (b) reconfigure LEASE PREFERENCES to place leaseholders in the region with highest write traffic; (c) consider migrating data to a different regional home if usage patterns shift permanently; (d) use CockroachDB\'s leaseholder rebalancing or Spanner\'s zone-aware placement; (e) if writes come from multiple regions roughly equally, consider regional-by-row instead. The general principle: leaseholder placement drives write latency for regional tables; align leaseholder location with primary write source.

The composite pattern across all five is that geo-distributed database performance is dominated by placement decisions, not by the raw performance of the database software. A well-placed CockroachDB deployment can serve millions of reads per second at single-digit ms latency; a poorly-placed one serves hundreds of writes per second at hundreds of ms latency. Same software, radically different production performance. The specific engineering task: match each table\'s placement pattern to its workload, monitor for pattern-workload mismatches, and adjust as workloads evolve. Modern distributed databases provide the placement APIs; using them correctly is the specific Expert-tier competence for geo-distributed data architecture. Getting this right at architecture time avoids expensive rebuilds later; getting it wrong forces migration under time pressure with production traffic.

Every geo-latency bug is a placement mismatch. Match placement pattern to workload characteristics at architecture time; adjust as workloads evolve; use the specific placement APIs modern distributed SQL provides.
§ 06 — Eight words for the geo-distribution conversation

Vocabulary,
for the geography case.

The terms that show up in every distributed database placement design, every "why is cross-region latency killing us?" investigation, every GDPR/data-residency compliance review.

TrueTime
/truː taɪm/
Google\'s bounded-uncertainty clock service using GPS receivers + atomic clocks in every datacenter. Exposes TT.now() returning [earliest, latest] interval. Typical uncertainty: 1-7ms. Enables Spanner\'s external consistency via commit-wait.
Commit-Wait
/kəˈmɪt weɪt/
Spanner\'s specific mechanism: after picking commit_ts = TT.now().latest, wait until TT.now().earliest > commit_ts before acknowledging client. Cost: uncertainty duration (~7ms). Provides external consistency without extra round-trips.
External Consistency
/ɪkˈstɜːrnəl/
Strict serializability: transactions ordered by real wall-clock time. Stronger than serializability. Required for audit trails, regulatory compliance, cross-session user semantics. Spanner\'s specific offering via TrueTime + commit-wait.
Follower Read
/ˈfɒloʊər riːd/
Reads served from any replica, not just leader/leaseholder. Cost: bounded staleness (5-30s typical). Benefit: sub-millisecond local reads without cross-region round-trips. Standard for read-heavy workloads with staleness tolerance.
Leaseholder
/ˈliːshoʊldər/
CockroachDB term for the replica that serves reads and processes writes for a range. Similar to leader in Raft but decoupled — leaseholder can be in a different zone than raft leader. Placement drives write latency for regional tables.
Regional Table
/ˈriːdʒənəl/
Placement pattern: data lives in one region with multi-zone replication for durability. Local ops fast (5-10ms); cross-region ops pay full RTT. CockroachDB REGIONAL BY TABLE. Best for region-specific data and regulatory data residency.
Global Table
/ˈɡloʊbəl/
Placement pattern: data replicated to all regions. Reads fast everywhere; writes slow (100-300ms cross-region quorum). CockroachDB GLOBAL. Best for read-mostly reference data — catalogs, currency rates, feature flags.
Locality-Aware Placement
/loʊˈkælɪti/
Configuring which regions/zones host which data via database placement APIs. Includes REGIONAL BY ROW, GLOBAL, REGIONAL BY TABLE, LEASE PREFERENCES. The specific engineering discipline for geo-distributed data.
§ 07 — Knowledge check

Five questions.
The geographic intuition.

Test the placement. Click an answer; explanation drops in instantly.

QUESTION 1 OF 5
Loading question...
Score: 0 / 5
5 / 5

Geography earned.

Perfect. TrueTime bounded uncertainty, commit-wait for external consistency, regional/global/regional-by-row placement, follower reads with bounded staleness, leaseholder placement — the specific engineering for sub-100ms global-scale distributed transactions. Next up: M.53, storage engine internals.

§ 08 — The recap

Three ideas to
carry forward.

The composite understanding that turns "geo-distribution is hard" into "geo-distribution is a specific engineering discipline with specific techniques."

i

Physics has a floor

Speed of light gives ~5ms per 1000km one-way. NYC-LON is 76ms actual RTT; NYC-TYO is 150ms; LON-SYD is 300ms. Every cross-region round-trip in your protocol pays this. The engineering task is not making the network faster (impossible) but minimizing the number of round-trips per operation through protocol design and placement.

ii

TrueTime enables commit-wait

Spanner\'s specific mechanism: bounded-uncertainty clock (TT.now() returns [earliest, latest]) plus commit-wait (wait out uncertainty after picking commit timestamp). Provides external consistency without extra round-trips. Cost: ~7ms commit-wait vs 60-200ms extra RTT in classical protocols. CockroachDB\'s HLC approach is the alternative for teams without atomic clocks.

iii

Placement is the leverage

Three specific patterns: REGIONAL (data in one region, fast local, slow remote), GLOBAL (replicated everywhere, fast reads global, slow writes global), REGIONAL BY ROW (each row in its home region, per-record optimization). Mix per table based on read/write ratio and access patterns. Follower reads for latency-optimized reads. This is the specific engineering discipline that makes global-scale strong-consistency practical.

↓ UP NEXT · PHASE J CONTINUES

M.53 — Storage
engine internals.

The next Expert module. Below the transaction layer sits the storage engine — LSM trees, B+ trees, columnar formats, page management, compaction, WAL. Understanding storage engine internals is what turns "we use PostgreSQL" into "we understand exactly why our workload hits its throughput ceiling."

Continue to Module 53 →