How it works
Spanner organizes table and index data into ordered key ranges called splits. It automatically splits and redistributes ranges as data and load grow, but the primary key still determines locality and potential hotspots. Automatic splitting cannot make concurrent updates to one row scale without contention.
Each split is replicated through a Paxos group with an elected leader. The leader coordinates writes, and a voting quorum must participate for progress. Read-write replicas store data and vote; witness replicas vote without serving reads; read-only replicas serve reads without voting.
A read-write transaction that touches multiple splits uses two-phase commit across the participating groups. Paxos makes each group's state durable across replica failures, while two-phase commit coordinates the atomic outcome across groups. These mechanisms solve different problems and both add coordination.
TrueTime exposes a bounded interval for the current time rather than pretending clocks are perfectly synchronized. Spanner combines timestamp assignment with commit wait to support external consistency: transactions using its default serializable isolation respect the real-time order of completed transactions. This does not mean every read must contact every region.
Spanner keeps multiple data versions using MVCC. Read-only transactions can read a consistent snapshot without taking read-write transaction locks, while default serializable read-write transactions use locking and can abort under contention. SQL queries may execute across multiple splits, so access paths, indexes, and transaction scope still matter.
What it gives you in a design
- Distributed relational transactions
- Atomically update related rows even when they live on different splits. This is useful for inventory reservations and ledger entries, but a wide transaction costs more coordination than a localized one.
- External consistency
- With default serializable transactions, transaction order respects real-time precedence. State the isolation and read mode explicitly rather than assuming every supported mode has identical guarantees.
- Strong and stale snapshot reads
- Strong reads return a consistent view of current committed data, while stale reads trade freshness for opportunities to serve reads closer to clients. Choose staleness separately for browsing, reporting, and correctness-sensitive decisions.
- Automatic data distribution
- Spanner manages splits and their placement as the database grows. You still need keys that distribute writes and enough provisioned compute to handle the workload.
- Secondary indexes and interleaved tables
- Secondary indexes support alternative access paths but add write work and can introduce their own hotspots. Interleaved tables can improve parent-child locality when the schema and access patterns align.
- Change streams
- Change streams expose committed data changes for downstream processing, such as updating search indexes or analytics systems. Consumers still need durable progress tracking and retry-safe processing; a stream does not make external side effects exactly once.
Scaling, replication and failure
Design the primary key around both distribution and access patterns. A leading monotonically increasing timestamp or sequence can concentrate inserts at the end of one key range; hashing, UUIDs, or bit-reversed sequences can spread writes, with corresponding costs for ordered scans and locality. Evaluate secondary-index keys for the same problem.
Adding compute increases available capacity, but useful throughput depends on split distribution, query efficiency, and contention. A single inventory row, account balance, or global counter remains a serialization point. Keep transactions short, index selective predicates, and separate high-volume derived counters from authoritative transactional state when the requirements allow it.
Regional and multi-region configurations make different latency and failure-domain trade-offs. Writes must reach the leader and the required voting quorum, so client placement, leader placement, and replica topology affect latency. Read-only replicas can expand read placement without automatically making write coordination cheaper.
Failures are handled through replicated state and leader election. Writes can continue only where the relevant groups retain a quorum; a partitioned minority cannot independently accept conflicting writes. Regional survival depends on the chosen configuration, and some stale reads may remain possible even when fresh reads or writes cannot proceed.
Limits and defaults worth knowing
Check the current documentation before relying on an exact value; many of these are configurable.
| Commit size | A commit is limited to 100 MiB, including index and change-stream data. Large logical jobs must be divided into bounded transactions. |
|---|---|
| Mutations per commit | A commit supports up to 80,000 mutations, including mutations generated for indexes. This is not a simple limit on the number of rows an application can update. |
| Version retention | The version retention period defaults to 1 hour and is configurable up to 7 days. Historical reads must fall within retained history. |
| Default transaction isolation | Read-write transactions default to serializable isolation. If selecting another supported isolation mode, reassess the anomalies and guarantees rather than carrying over the default assumptions. |
Use it when
- The design needs atomic updates across records that may be distributed across many servers.
- A growing relational workload needs horizontal scaling without application-managed shard routing.
- Multi-region durability and strong transactional correctness matter more than minimizing write latency.
- The team wants managed replication and failover and can justify the operational and monetary trade-offs.
Avoid it when
- A single-region PostgreSQL or MySQL deployment comfortably meets the scale and availability requirements with less cost and complexity.
- The application must accept writes independently on both sides of a network partition and reconcile them later.
- The main workload is large analytical scans, media storage, or high-volume telemetry with little need for relational transactions.
- The throughput target depends on repeatedly updating one globally shared row at very low latency; horizontal database scaling does not remove that contention.
What interviewers ask about it
Follow-ups you can expect once Spanner is on your whiteboard, and the core of a strong answer.
- How does Spanner provide external consistency without perfectly synchronized clocks?
- TrueTime reports a time interval containing the actual time, and Spanner uses timestamp assignment plus commit wait to account for that uncertainty. Combined with transaction concurrency control and replication, this lets default serializable transactions respect real-time order.
- Why does Spanner need both Paxos and two-phase commit?
- Paxos replicates the state of an individual split and supports safe progress despite replica failures. Two-phase commit coordinates one atomic transaction across multiple splits, with participant and coordinator state replicated for recovery.
- What happens if a region becomes isolated?
- Groups that retain a voting quorum can continue making progress, potentially after leader election. A side without quorum cannot accept independent writes, and whether the system tolerates the regional loss depends on the configured replica layout.
- How would you prevent write hotspots?
- Avoid concentrating new writes under a monotonically increasing leading key, and inspect index keys as well as table keys. Spread independent writes across key ranges, but recognize that a single heavily updated record requires an application-level redesign rather than more splits.
- How do you handle transaction retries and an uncertain commit result?
- An aborted transaction can require rerunning the entire transaction callback, so it must not send emails, charge cards, or perform other irreversible external actions. For uncertain outcomes, use a durable operation ID and check transactional state before issuing another logical operation.
- Does Spanner eliminate the need for sagas or an outbox?
- It can eliminate some application-managed coordination when all affected state is inside one Spanner database transaction. Payments, queues, and other external services remain outside that boundary, so an outbox, idempotency, and compensating workflows may still be necessary.
Common mistakes
- Saying that TrueTime replaces consensus or makes clock uncertainty disappear.
- Assuming automatic splitting fixes a hot row or an append-only hotspot immediately.
- Claiming multi-region deployment gives local, low-latency writes everywhere without quorum coordination.
- Treating a database transaction as an atomic boundary that includes external APIs, or putting external side effects inside a retried transaction callback.
Alternatives
- PostgreSQL or MySQL
- Choose a conventional relational database when one writable primary and its replicas meet the requirements. It usually offers a simpler starting point and avoids distributed transaction coordination for ordinary local transactions.
- CockroachDB
- Consider it when distributed SQL and serializable transactions are needed but deployment flexibility or avoiding a Google Cloud-specific service is important. Compare locality controls, failure behavior, SQL compatibility, and operating responsibilities.
- DynamoDB
- Consider it for predictable key-based access patterns in AWS when broad relational queries and cross-partition relational transactions are not the core requirement. Evaluate transaction scope and the consistency mode of the selected global-table configuration explicitly.
- BigQuery
- Choose it for warehouse-style analytical queries over large datasets rather than latency-sensitive transactional updates. A common design keeps authoritative transactional state in Spanner and exports changes for analytics.
Where it comes up
Interview questions where Spanner is a natural fit, and why.
- Design a payment systemSpanner can hold idempotency records, balances, and ledger entries in one transaction while external payment processing remains a separate reliability boundary.
- Design a ticket booking system like TicketmasterSerializable transactions can enforce exclusive seat allocation, but contention on popular inventory still requires admission control and short transactions.
- Design a hotel booking systemA transaction can atomically reserve inventory across multiple nights while coordinating hold expiration and payment state.
- Design a wire transfer systemDistributed transactions can atomically record balanced ledger entries and transfer state without making the external bank call part of that transaction.
- Design Netflix's concurrent screen limitStrong transactional admission checks can prevent concurrent regional requests from allocating more account-wide playback slots than allowed.
Questions people ask
Is Google Spanner SQL or NoSQL?
Google Spanner is a relational SQL database with schemas, indexes, and ACID transactions. It also distributes storage and execution across servers, so relational modeling does not remove the need to think about keys, locality, and distributed query costs.
Is Google Spanner strongly consistent?
Yes. Its default serializable transactions provide external consistency, which includes respecting real-time transaction order. It also supports stale reads and other isolation choices, so describe the guarantees of the mode your application actually uses.
What is the difference between Google Spanner and Cloud SQL?
Spanner is designed for horizontally distributed relational storage and transactions, including multi-region configurations. Cloud SQL manages conventional database engines such as PostgreSQL and MySQL, generally using a writable primary with replicas and high-availability options. Choose based on scale, SQL compatibility, latency, and failure requirements rather than assuming Spanner is always the next upgrade.