Google Cloud Spanner’s Write Lock Pricing Forces a PostgreSQL Team to Relearn Transaction Visibility

Jul 14, 2026 By Deepa Iyer

When a mid-stage startup decided to migrate its PostgreSQL-backed analytics platform to Google Cloud Spanner in early 2022, the team expected a straightforward scaling story. Spanner promised global strong consistency, automatic sharding, and no more manual partition management. What they did not anticipate was a new line item on their monthly cloud bill: write-lock operations. Each row-level lock during a read-write transaction cost a small but nonzero amount. By the third month, lock costs accounted for roughly 40% of their total Spanner spend. The PostgreSQL team, accustomed to a world where transaction visibility came free with multi-version concurrency control, had to relearn how to think about locks—not just as a performance concern, but as a direct cost driver.

The Lock That Costs a Dime a Row

Spanner's pricing model charges for each lock operation during read-write transactions. As of late 2024, the per-lock fee is small—on the order of a fraction of a cent—but it adds up quickly under write-heavy workloads. A single transaction that updates 10,000 rows incurs 10,000 lock operations, each billed separately. For a team processing millions of writes per hour, the lock costs can easily surpass compute and storage charges.

The PostgreSQL team in question had designed their application around short, frequent writes—a pattern that works well with PostgreSQL's MVCC, where locks are lightweight and not metered. When they ported the same logic to Spanner, they found that each UPDATE statement was locking rows for the duration of the transaction. Even with careful use of secondary indexes and batched writes, the lock count per transaction remained high.

Lock contention became a budget line item. The team began monitoring lock-wait metrics as closely as CPU utilization. They discovered that long-running transactions were particularly expensive, because locks are held until commit, blocking other writers and increasing the total lock-seconds billed. The old assumption that transaction visibility is free—inherited from PostgreSQL's snapshot isolation—broke under Spanner's metering model.

One engineer described the shock: "We went from paying for CPU and storage to paying for every lock we take. It's like being charged per page fault." The team had to re-architect their write patterns to minimize lock duration and lock count, sometimes sacrificing read freshness to avoid lock costs altogether.

Spanner's Consistency Trade-Off: Money vs. Staleness

Spanner's strong consistency is powered by TrueTime, Google's globally synchronized clock infrastructure. TrueTime ensures that read-write transactions see a consistent snapshot across all regions, but this guarantee comes at a cost. Each read-write transaction must coordinate with TrueTime, adding latency and requiring locks on the involved partitions.

For teams accustomed to PostgreSQL's snapshot isolation—where reads never block writes and writes never block reads—Spanner's read-write transactions can feel punitive. A read-write transaction in Spanner locks the rows it reads, even if it only reads them. This means that a simple SELECT followed by an UPDATE can lock rows for the entire transaction duration, potentially blocking other writers and inflating the lock bill.

Spanner offers stale reads as a cheaper alternative. Stale reads return data from a timestamp a few seconds in the past, avoiding locks entirely. But stale reads are not suitable for all application logic. The PostgreSQL team found that critical paths—like inventory updates or payment processing—required fresh data and thus paid the lock premium. Less critical analytics queries were migrated to stale reads, cutting lock costs by roughly 30%.

The trade-off is stark: pay for strong consistency or accept staleness. For a team used to PostgreSQL's single-node snapshot isolation, where stale reads are the exception rather than the rule, this was a painful adjustment. The cost of global consistency is not just latency—it is a direct line item on the invoice.

PostgreSQL's MVCC Assumptions Don't Survive Spanner

PostgreSQL's multi-version concurrency control (MVCC) is the bedrock of its transaction isolation. Each transaction sees a snapshot of the database at its start time, determined by transaction ID ordering. Locks are used only for write-write conflicts, not for reads. This design means that read-heavy workloads can scale without lock contention, and there is no per-lock pricing.

In Spanner, the concurrency model is fundamentally different. Spanner uses a combination of pessimistic locking and timestamp ordering to achieve serializable isolation. Every read-write transaction must acquire locks on the rows it accesses, and these locks are tracked per shard. The lock table itself is a distributed data structure that incurs storage and compute costs, passed on to the user as lock fees.

The PostgreSQL team's migration revealed that many of their query patterns relied on implicit lock avoidance. For example, they used SERIALIZABLE isolation in PostgreSQL, which uses optimistic concurrency control and aborts on conflict rather than locking. Spanner's serializable mode is pessimistic by default, locking rows on read. The team had to rewrite many transactions to use explicit locking or to reduce the number of rows touched per transaction.

One common pattern was a bulk update that scanned a large table and updated a subset of rows. In PostgreSQL, this would use a single snapshot and avoid locking unmodified rows. In Spanner, the scan itself would lock the entire partition unless the query used a stale read. The team eventually split bulk updates into smaller batches, each touching fewer rows, to keep lock costs under control.

CockroachDB: The Middle Ground That Charges by CPU

CockroachDB, like Spanner, is a distributed SQL database that offers global consistency through a clock synchronization mechanism (hybrid logical clocks). But its pricing model is closer to traditional databases: it charges per CPU hour, not per lock operation. This difference has significant implications for write-heavy workloads.

CockroachDB achieves serializable isolation without explicit lock costs. It uses a combination of optimistic concurrency and timestamp ordering, aborting transactions on conflict rather than locking rows. This means that write-heavy workloads can run without incurring per-row lock fees. However, write contention still hurts performance: conflicting transactions are aborted and retried, increasing latency and CPU usage.

For the PostgreSQL team evaluating alternatives, CockroachDB offered a more predictable cost model. Their write-heavy workload would not surprise them with lock charges. But they found that CockroachDB's performance under high contention was worse than Spanner's, because aborted transactions wasted CPU cycles. The team ran benchmarks showing that at 30% write contention, CockroachDB's throughput dropped by roughly 40% compared to Spanner's lock-based approach.

The choice between Spanner and CockroachDB often comes down to workload characteristics. Spanner's pricing punishes write-heavy workloads with lock fees, but its pessimistic locking can handle high contention more gracefully. CockroachDB's CPU-based pricing aligns cost with compute usage, but its optimistic concurrency can lead to wasted resources under contention. Neither is a drop-in replacement for PostgreSQL, but each offers different economics.

Real-World Numbers: A Migration Story

The startup that moved from PostgreSQL to Spanner in 2022 saw its monthly database bill jump from roughly $8,000 to $24,000 after migration. Of that increase, lock costs accounted for about $6,400—nearly 40% of the Spanner spend. The team had not budgeted for this. Their initial cost estimates, based on compute and storage alone, were off by a factor of two.

To mitigate the lock costs, the team added read replicas in Spanner. Read replicas serve stale reads without incurring lock fees, because they do not participate in write transactions. By routing all non-critical reads to replicas, the team reduced lock costs by roughly 25%. But this introduced operational complexity: replica lag had to be monitored, and some queries needed freshness guarantees that replicas could not provide.

After six months, the team adopted a hybrid architecture. They kept Spanner for read-heavy and globally distributed workloads, but moved write-heavy transactional logic back to a self-managed PostgreSQL cluster. The PostgreSQL cluster handled roughly 60% of writes, while Spanner handled 90% of reads. The combined bill dropped to $15,000 per month, still higher than the original PostgreSQL setup but with better global latency.

This migration story is not unique. Other teams have reported similar experiences on forums and conference talks. The lesson is that distributed SQL pricing models are not interchangeable with monolithic databases. Lock costs, in particular, are a hidden tax that can double or triple a cloud bill for write-heavy applications.

What a Distributed SQL Buyer Should Ask

Before signing a contract for a distributed SQL database, teams should ask vendors for a lock-cost simulation based on their actual workload. Spanner's pricing documentation is transparent about per-lock fees, but many teams overlook them until the first bill arrives. A simulation should include read-write transactions, lock duration, and contention patterns.

Benchmark with your own write patterns. Do not rely on synthetic benchmarks that use trivial workloads. Run a week-long trial with production-like traffic and monitor lock-related metrics. Spanner provides lock-wait charts in its console; CockroachDB provides transaction retry rates. Use these to estimate costs under load.

Check whether the vendor charges per lock or per CPU. Spanner charges per lock; CockroachDB charges per CPU hour. For write-heavy workloads, CPU-based pricing is often more predictable. But for read-heavy workloads with low contention, Spanner's lock costs may be negligible. The right choice depends on your ratio of reads to writes and the level of contention.

Consider eventual consistency for non-critical reads. Both Spanner and CockroachDB offer stale reads or follower reads at reduced cost. Design your application to tolerate staleness where possible. This can cut lock costs by 30–50% in Spanner, and reduce CPU usage in CockroachDB. Negotiate burst credits for lock-heavy months. Some cloud vendors offer volume discounts or credits for sustained usage. Ask for a pricing model that caps lock costs as a percentage of total spend.

Finally, do not assume that distributed SQL is a drop-in replacement for PostgreSQL. The migration story above shows that even with careful planning, hidden costs can emerge. Run a proof of concept with real traffic and real cost monitoring before committing to a multi-year contract. The transparency of pricing models is improving, but the burden of due diligence still falls on the buyer.

Alternative Approaches: TiDB and YugabyteDB

While Spanner and CockroachDB dominate the conversation, other distributed SQL databases offer different cost and consistency trade-offs. TiDB, for example, uses a shared-storage architecture with a separation of compute and storage, and it charges primarily for compute nodes and storage, not per lock. TiDB's pricing is based on the number of TiKV nodes (storage) and TiDB nodes (compute), which makes it more predictable for write-heavy workloads. However, TiDB's consistency model is snapshot isolation, which may be weaker than Spanner's strict serializable isolation. For applications that can tolerate slightly stale reads, TiDB's cost model can be attractive.

YugabyteDB is another contender, built on a foundation similar to CockroachDB but with a focus on PostgreSQL compatibility. Its pricing is also CPU-based, but YugabyteDB offers a "read replica" feature that can reduce lock costs by serving reads from follower nodes. The PostgreSQL team's hybrid architecture with Spanner could have been replicated using YugabyteDB with read replicas, potentially at a lower total cost. However, YugabyteDB's lock management is less transparent than Spanner's, and some teams have reported unexpected CPU spikes under contention.

The key takeaway is that no two distributed SQL databases have the same pricing model. Teams should evaluate at least three vendors—Spanner, CockroachDB, and one alternative like TiDB or YugabyteDB—using their own workload patterns. A cost comparison should include not only the per-lock or per-CPU charges, but also the cost of read replicas, cross-region replication, and data transfer.

Counter-Argument: When Lock Costs Are Acceptable

Not every workload suffers from Spanner's lock pricing. For read-mostly applications with infrequent writes, lock costs are negligible. A typical e-commerce catalog that updates prices once per day and serves millions of reads will see lock fees that are a tiny fraction of the total bill. Similarly, applications that use Spanner's partitioned DML to batch updates can reduce the number of lock operations by updating many rows in a single transaction, though this increases lock duration.

Spanner also offers a "read-only" transaction mode that does not acquire locks. For workloads that can use read-only transactions for all reads, lock costs vanish. However, read-only transactions still require a consistent snapshot, which Spanner provides via TrueTime without locking. The PostgreSQL team's mistake was using read-write transactions for all operations, including reads that could have been read-only.

Some teams argue that the lock costs are a feature, not a bug. By charging per lock, Spanner incentivizes developers to write more efficient transactions—shorter, fewer rows touched, and less contention. This can lead to better overall system performance and lower CPU usage. In this view, the lock fee is a signal that encourages good engineering discipline. The PostgreSQL team's experience, while painful, forced them to optimize their queries and reduce unnecessary locking, which improved latency and throughput.

Future Trends: Pricing Evolution

Cloud database pricing is still evolving. Google has introduced committed use discounts for Spanner that can reduce lock costs by up to 40% for long-term contracts. CockroachDB has experimented with burstable CPU credits that cap costs during spikes. It is possible that within a few years, all distributed SQL vendors will converge on a hybrid model that charges a base fee for compute and storage, with a small surcharge for lock operations that exceeds a threshold.

Another trend is the rise of serverless database offerings that charge per operation, similar to Spanner's lock model. Amazon Aurora Serverless v2, for example, charges per ACU (Aurora Capacity Unit) per hour, but does not charge per lock. However, Aurora's consistency model is weaker than Spanner's, and it does not offer global strong consistency out of the box. The trade-off between cost and consistency will continue to be a central decision for architects.

The PostgreSQL team's story is a cautionary tale, but it also highlights the importance of understanding the operational model of a database before migrating. As distributed SQL becomes more mainstream, the gap between monolithic and distributed pricing will narrow, but for now, teams must do their homework. The lock that costs a dime a row may be the most expensive lesson in cloud database economics.

Recommend Posts
Tech

A Cloud Team Paid Three Different Chip Vendors for the Same SHA-256 Hash

By Sara Park/Jul 14, 2026

A cloud team ran the same SHA-256 hash on Intel, AMD, and AWS Nitro hardware and got three different bills. This is the economics of the hardware-software boundary, where identical computations cost wildly different amounts depending on which chip vendor you choose.
Tech

FPGA Inference Pipeline Paid Per LUT Rewrites a Billion-Token Batch Economy

By Yusuke Tanaka/Jul 14, 2026

How LUT-based FPGA inference cuts per-token cost below GPU for billion-token batches, reshaping LLM deployment economics and API-level design.
Tech

One BGP Session, Three Transit Providers, and a Peering Invoice That Rewrites Latency

By Yusuke Tanaka/Jul 14, 2026

A peering invoice from a single BGP session revealed how transit costs, not fiber distance, dictated latency. A contrarian take on network engineering in 2026.
Tech

Pixel 8a Ships with One DSP Radio Stack as Qualcomm Tunes the Other

By Sara Park/Jul 15, 2026

Google's Pixel 8a ships with one of two DSP radio stacks active while Qualcomm tunes the other post-launch. This dual-stack approach reveals how modem firmware constraints shape Android development.
Tech

Maintaining an Open Source Package for Six Years Taught Me Contract Law

By Yusuke Tanaka/Jul 15, 2026

Six years maintaining an open source package taught a solo developer that license terms are contracts. A practical guide to governance, liability, and legal hygiene for maintainers.
Tech

One Open Source License Rewrote Its Compatibility Clause After Three Corporate Forks

By Yusuke Tanaka/Jul 14, 2026

How three corporate forks of a copyleft license forced its maintainers to rewrite the compatibility clause, closing loopholes and reshaping downstream project choices.
Tech

One SwiftUI App Store Review Bans Five Cross-Platform Libraries Our Team Depended On

By Sara Park/Jul 15, 2026

A single App Store rejection banned five cross-platform libraries our team had relied on for two years, forcing costly rewrites and exposing the fragility of third-party stacks in iOS development.
Tech

Cache Ejections at the European Edge Double a Transit Provider's Per-Region Bill

By Yusuke Tanaka/Jul 14, 2026

European edge nodes eject caches faster due to ISP fragmentation and low TTLs, doubling per-region bills for transit providers. Tuning with Fastly VCL or AWS Origin Shield can cut costs but adds latency or CPU overhead.
Tech

Three Database Engines Claim Linearizable Reads as a Clock Skid Resets One Team's Consensus

By Lucas Mendes/Jul 15, 2026

A fintech incident reveals how clock skew breaks linearizable reads in CockroachDB and YugabyteDB. Analysis of trade-offs, mitigations, and choosing the right engine.
Tech

Ethernet MAC Hardware Offload Exposes a UDP Jitter Bug That Two Kernel Stacks Hide Differently

By Sara Park/Jul 14, 2026

A deep-dive into how Linux and FreeBSD handle UDP jitter differently under hardware MAC offload, revealing a timestamp-ordering bug in Intel XL710 NICs and practical trade-offs for real-time workloads.
Tech

Saga Pattern vs Two-Phase Commit: Two Distributed Transaction Lies That Fail Differently

By Deepa Iyer/Jul 14, 2026

Both Two-Phase Commit and Saga Pattern promise distributed transaction consistency, but each fails in its own way. A pragmatic breakdown of when each works, where they break, and what practitioners actually do in production.
Tech

BGP Hijack Insurance Rewrote One ISP’s Transit Bill in Four Hours

By Sara Park/Jul 15, 2026

How one ISP turned a BGP hijack into a transit insurance payout, rewriting the economics of network reliability and path integrity.
Tech

A Single Signed SBOM Commit Killed a Friday Afternoon’s Production Patch

By Deepa Iyer/Jul 15, 2026

When a signed SBOM commit triggered a production pipeline failure, a team learned the hard way that supply-chain security gating has real operational costs. This is what working with signed attestations looks like in 2026.
Tech

Google Cloud Spanner’s Write Lock Pricing Forces a PostgreSQL Team to Relearn Transaction Visibility

By Deepa Iyer/Jul 14, 2026

A PostgreSQL team migrating to Google Cloud Spanner discovered that per-write-lock pricing can dominate cloud bills. This article compares Spanner, PostgreSQL, and CockroachDB on cost, consistency, and lock behavior.
Tech

Open Source Maintainers Bill the Corporation That Forked Their Stack

By Sara Park/Jul 15, 2026

When corporations fork open source projects and monetize them without contributing back, maintainers are fighting back with new licensing models, foundations, and billing strategies.
Tech

Six Engineers Maintain Two Rendering Engines as One Company Owns the DOM

By Lucas Mendes/Jul 14, 2026

React and Vue both maintain separate virtual DOM implementations, each requiring dedicated teams. This article examines the economic and engineering costs of dual rendering engines, corporate ownership, and what a unified standard might look like.
Tech

Paying a License Fee Every Time an Open Source Maintainer Quits

By Lucas Mendes/Jul 15, 2026

When a critical open-source maintainer quits, downstream users pay a hidden tax. This article explores why licenses stay silent, how corporate users extract value, and what market mechanisms could fix the gap.
Tech

Apple's App Store Commission Rewrites the Cost of a SwiftUI Gesture Handler

By Yusuke Tanaka/Jul 14, 2026

A $0.99 SwiftUI gesture handler reveals how Apple's 30% commission and platform lock-in reshape developer economics compared to Android's more open model.
Tech

Service Mesh Overhead That Bills Per Sidecar Rewrites a Kubernetes Team’s Capacity Budget

By Deepa Iyer/Jul 14, 2026

Per-sidecar billing from service meshes like Istio and Linkerd can inflate Kubernetes costs by 30-40%. This article examines the hidden overhead, real-world case studies, and alternatives like eBPF and ambient mesh.
Tech

One Data Scientist Runs Inference on Three GPU Vendors and Every Bill Differs

By Sara Park/Jul 14, 2026

A data scientist runs identical LLM inference workloads on AWS, GCP, and Azure. The bills differ wildly. Here's why GPU pricing is still a black box in 2026.