Skip to content
About
Main content

Bounded clock uncertainty

How do systems order transactions by real time, and where is clock uncertainty billed?

You want timestamps whose order agrees with real time: a transaction that finished before another began must get a smaller timestamp. This is called . Physical clocks on different machines disagree. Logical clocks (counters such as Lamport clocks) capture causality ("this message came after that one") but say nothing about transactions that never communicated, which is exactly the pair you need to order.

Hybrid Logical Clocks (HLC) combine a physical clock reading with a logical counter. Take the maximum of the local clock and any timestamp you received; increase the counter on ties. Causality is always respected, and timestamps stay within the clock skew of physical time. What does not give is external consistency for non-communicating transactions. So CockroachDB adds a maximum-offset assumption and an : a read that meets a value inside its uncertainty window must restart at a higher timestamp. The price of loose clocks is thus paid in read-path restarts, in proportion to the clock skew.

TrueTime (Google Spanner) takes the other route. The clock API returns an interval guaranteed to contain the true time. The interval spans ±ε around the true time, kept small with GPS receivers and atomic clocks: a few milliseconds, up to about 7 in Spanner's published figures. The mechanism is : after choosing a timestamp s, the waits until the earliest bound of the interval is later than s, and only then releases and acknowledges. When the transaction becomes visible, s is unambiguously in the past everywhere.

Two things to take from this:

  1. The wait does no work. It is pure bought to compensate for an assumption that the node cannot check locally: that its clock is right. So ε converts directly into money. Spanner's investment in GPS receivers and atomic clocks in every datacenter is money spent to shorten a wait inside a correctness protocol. In practice, the wait overlaps with the decision broadcast, so the effective cost is the larger of the two, not their sum. That is why the latency is tolerable.
  2. This is the cleanest instance of "costs are conserved" in this whole mechanism: Spanner bills it on the write path, as a wait. CockroachDB bills it on the read path, as restarts. Same ε, same physics, two invoices. The right choice depends on your read/write ratio, not on which design is "better".

Claim to test. "Spanner requires atomic clocks" is folklore. It requires bounded uncertainty; the special hardware makes the bound small. Cloud providers now offer microsecond-level bounded time without private atomic-clock infrastructure. So this is current engineering reality moving, not a permanent constraint, and it is a claim to re-check rather than memorize.