Clocks: three requirements
What does measuring a duration, bounding a lease and ordering events each need from a clock?
Clocks: three different requirements, three different assumptions
Mixing these up is the most common source of wrong intuition, including the widespread folklore that clocks are simply untrustworthy.
- Measure a duration (timeouts, heartbeat intervals, latency). This needs a monotonic clock and nothing shared. Wall-clock time can step backwards after a time-sync correction, and computing a duration by subtracting two wall-clock readings is the single most common concrete bug in this area.
- Bound staleness across machines (leases). This needs a bound on drift rate, not on offset, because both parties measure an interval and do not compare instants. Untamed quartz crystals drift 10–100 ppm (parts per million; up to several seconds per day). Disciplined clocks run at about 1–10 ppm. The lease's safety margin is that rate times the lease length.
- Order events across machines. This needs either causality tracking or a bounded offset. NTP offers roughly 1–10 ms over a WAN and sub-millisecond on a LAN. PTP (a more precise protocol) reaches microseconds with hardware support.
Causality without physical time
- Lamport clocks guarantee that if event a happened before b (a → b), then L(a) < L(b). Nothing is guaranteed about the converse. They give a consistent arbitrary total order and cannot detect concurrency.
- Vector clocks detect concurrency exactly, at O(N) per event, where N is the number of writers that have ever participated. That width grows without bound, so it needs pruning, and pruning is unsound in general. This is "a fixed number meets growth" and "cleaner with an unverifiable retention parameter" arriving together in one data structure. It is the reason version vectors in production systems carry a heuristic expiry that everyone knows is approximate.
- HLC (hybrid logical clock) bolts a physical reading onto a logical clock, so that causality holds and values stay human-meaningful. Its use for ordering transactions is a topic of its own.
The correction
"Never trust clocks" was right about the systems of 2010 and is wrong now. Cloud time services with hardware references, and, more importantly, an exposed error bound (Google's TrueTime ε, AWS ClockBound), make time a usable safety primitive. The precise statement:
An accurate clock with no bound is unusable for safety. A mediocre clock with an honest bound is usable, and you pay the bound as waiting. This is current engineering reality with a clear improvement trend, not a permanent constraint.
Compression: timeouts need a stopwatch, leases need a bounded rate, ordering needs causality or a bounded offset, and a clock becomes a safety primitive only when it reports its own error.