Lesson 4 / 33
Physical Clocks and Why They Lie
Explain clock skew, drift and NTP adjustments, and avoid ordering events by wall-clock timestamps.
By Rahul Agarwal · 15 years in web development
Each node has its own idea of 'now'
Every machine has a quartz clock that drifts: it runs slightly fast or slow, so two machines slowly disagree. NTP periodically corrects this, but only to within some milliseconds over a typical network, and a correction can make the time-of-day clock jump backwards. The gap between two clocks at one instant is called skew. Operating systems therefore offer two clocks: a wall clock (time of day, can jump) and a monotonic clock (only moves forward, meaningless across machines). Use the monotonic clock to measure durations such as timeouts on one node. Never use wall-clock timestamps from different nodes to decide which of two events happened first, because skew can be larger than the gap between the events. Systems that do rely on time, like Google Spanner with TrueTime, expose an explicit uncertainty interval and wait it out.
From wall clocks to logical clocks
Physical clocks drift apart, Lamport clocks give a consistent total order, and vector clocks additionally detect concurrency.
Last-writer-wins with a skewed clock loses data
Two replicas tag writes with their own wall clock and keep the highest timestamp. Replica B is 50 ms behind, so the newer write looks older and is silently discarded.
# Two replicas use wall-clock timestamps for last-writer-wins (LWW).
# Replica B's clock runs 50 ms behind replica A's.
writes = [
{"value": "price=100", "replica": "A", "ts": 1_000.000}, # happens first
{"value": "price=120", "replica": "B", "ts": 1_000.030 - 0.050}, # 30 ms later, skewed clock
]
winner = max(writes, key=lambda w: w["ts"])
print("real order : price=100 then price=120")
print("LWW keeps :", winner["value"])
Output:
real order : price=100 then price=120 LWW keeps : price=100
Monotonic for durations
In Python use time.monotonic(), in Go time.Since (Go's time.Time carries a monotonic reading), and in Java System.nanoTime() for elapsed time. Using wall-clock time for an election timeout can fire it instantly or never after an NTP step.
Quick check: Why is last-writer-wins by wall-clock timestamp risky across replicas?
- Timestamps take too much storage
- Clock skew can make a later write carry a smaller timestamp, so it is discarded
- Wall clocks cannot represent milliseconds
- It requires a consensus round for every read
Answer
Clock skew can make a later write carry a smaller timestamp, so it is discarded — If skew exceeds the real gap between two writes, the order by timestamp differs from the real order and the newer value is lost silently.