Distributed Systems · Paper 05 / 05

Spanner: Google's Globally-Distributed Database

James C. Corbett, Jeffrey Dean, Michael Epstein, Andrew Fikes, Christopher Frost, J. J. Furman, Sanjay Ghemawat, Andrey Gubarev, Christopher Heiser, Peter Hochschild, Wilson Hsieh, Sebastian Kanthak, Eugene Kogan, Hongyi Li, Alexander Lloyd, Sergey Melnik, David Mwaura, David Nagle, Sean Quinlan, Rajesh Rao, Lindsay Rolig, Yasushi Saito, Michal Szymaniak, Christopher Taylor, Ruth Wang, Dale Woodford

2012 · OSDI · ~13 min read

Read the original paper

Everyone said a database could not be both global and strongly consistent. Spanner did it by admitting that clocks are uncertain, and measuring the uncertainty.

The problem: a database that is global and still tells the truth

Google’s advertising business ran on a sharded MySQL deployment that took years to re-shard and could not survive a data centre outage without manual failover. The team wanted a database replicated synchronously across continents, with SQL and real transactions, that kept working when a whole region vanished. Bigtable offered the scale but no multi-row transactions; its successor Megastore offered transactions but wrote too slowly to be general. And one requirement seemed to rule out any global design: external consistency, which means that if transaction T2 starts after T1 has committed, anywhere on Earth, T2 must see T1’s writes and carry a later timestamp.

The obstacle is the one Lamport named in 1978. Timestamps from different machines cannot be compared, so a transaction committed in Tokyo and one committed in Dublin a millisecond later could easily be recorded in the wrong order, and a snapshot read in between would see an impossible history. Every previous system either routed all commits through one place, which does not scale across oceans, or gave up global ordering.

The idea: measure the clock error, then wait it out

Spanner’s answer is TrueTime, an API that refuses to pretend. Instead of a timestamp it returns an interval, [earliest, latest], that is guaranteed to contain the true time; the width of the interval, 2ε, is the uncertainty, and the system knows it at every moment. Behind the API are GPS receivers and atomic clocks in every data centre and a daemon on every machine that polls them and widens its interval between polls to cover drift. In the paper ε is typically between one and seven milliseconds.

TT.now() = [earliest, latest]true time is somewhere in here, guaranteed− ε+ εε ≈ 1–7 ms in the paper
A TrueTime reading. The true time is somewhere in the interval, guaranteed; the system is honest about how uncertain it is instead of picking a number.

How it works

Data is split into tablets, and each tablet is replicated across zones by its own Paxos group; a write is durable on a majority before the leader acknowledges it. A transaction that touches several tablets runs two-phase commit between their Paxos leaders, with the participants themselves replicated, so the classic weakness of two-phase commit, a coordinator that dies and leaves everyone waiting, cannot happen. Locks are held in the leaders; this is two-phase locking inside Paxos inside two-phase commit, and the paper is matter-of-fact about stacking them.

tablet: users a–mzone Azone Bzone CPaxos: leader in zone Atablet: users n–zzone Azone Bzone CPaxos: leader in zone Atablet: orderszone Azone Bzone CPaxos: leader in zone Aone transaction, two tablets: two-phase commit between the Paxos leaderseach write is durable on a majority of zones before the leader answers
The stack. Every tablet is a Paxos group spanning zones; a transaction across tablets runs two-phase commit between the groups’ leaders. Each layer replaces a single point of failure with a majority.
Try itWhy Spanner waits before it says yes

Drag the uncertainty. T1 takes the latest possible time as its timestamp, then waits until that moment is surely past. T2, which starts after T1 has replied, can only get a larger timestamp.

0 ms10 ms20 ms30 ms40 ms50 ms60 mstrue timeT1TT.now() = [10, 18]s1 = 18commit wait 4 ms, then replyT2starts after T1 replieds2 = 29 > s1
commit wait4msthe price of an honest timestamp
s2 − s111msalways positive: T2 is after T1 in real time
Spanner's ε in practice1–7msGPS and atomic clocks in every data centre

TrueTime never claims to know the time; it returns a window that is guaranteed to contain it. By waiting out the window, a transaction makes its timestamp mean something on every machine on Earth, and the cost is a few milliseconds, paid once per commit.

The payoff is reads. Because timestamps mean the same thing everywhere, Spanner can serve a snapshot read at any past timestamp from any replica that is caught up to it, without locks and without talking to the leader. A query over the whole database at “ten seconds ago” is consistent across every continent. Even schema changes become transactions with a timestamp in the future, applied simultaneously worldwide when the clock passes it.

What it changed

Spanner ended the assumption that global scale required giving up transactions, and started the category now called NewSQL. CockroachDB and YugabyteDB reproduce its architecture without special hardware, using hybrid logical clocks and accepting slightly weaker guarantees; TiDB takes a similar route. Google shipped Spanner itself as Cloud Spanner in 2017, and in 2024 Amazon’s Aurora DSQL adopted the same bounded-time approach using precise clock synchronisation. Brewer’s follow-up essay argues that Spanner is “effectively CA”: it is technically CP, but Google’s private network makes partitions so rare that users never see the difference.

Where you meet it today

  • Cloud Spanner, CockroachDB, YugabyteDB, TiDB. If a database advertises global strong consistency, it is some variation of this paper.
  • Bounded clocks as a service. AWS Time Sync and the ClockBound library expose an interval, not a number, so applications can play Spanner’s trick themselves.
  • Snapshot reads at a timestamp. “As of” queries and time-travel reads in modern databases descend from Spanner’s read-only transactions.
  • The design principle. When you cannot eliminate uncertainty, measure it and wait it out; the same idea reappears in leases, fencing tokens and lock expiry.
systemtime sourceguarantee across regions
SpannerTrueTime (GPS + atomic clocks)external consistency
CockroachDBhybrid logical clocks, NTPserialisable; linearisable within a bounded skew
Dynamo-stylevector clocks, no physical ordereventual, application merges