Two Clocks Never Agree
The previous piece was about storing time unambiguously. This one is about a subtler assumption underneath it: that the clock telling you the time is right. It’s close to right — usually within milliseconds of its peers, thanks to synchronization protocols quietly correcting drift in the background. But “close” is doing real work in that sentence, and the correction itself is a hazard: a clock that’s being adjusted can jump forward, and it can jump backward, which means the same machine can observe an earlier time than one it already recorded.
That’s why measuring elapsed time with the wall clock is a bug waiting for the right moment. Take a timestamp, do some work, take another, subtract — and if a sync happened in between, the answer can be wrong by the size of the correction, or negative. Negative durations are the funny outcome; the unfunny one is a timeout that silently becomes much longer or shorter than intended because the arithmetic underneath it drifted. Elapsed time wants a monotonic source — a counter guaranteed never to go backward — and most languages provide one distinct from the wall clock precisely because these are different questions. Wall time answers “when did this happen.” Monotonic time answers “how long did this take.” Using one for the other is the same category error as the instant/civil-time confusion from the last piece.
Across machines it gets worse, because there’s no shared clock to appeal to. Two servers writing rows with their own timestamps can produce a record where an effect precedes its cause by a few milliseconds, purely from skew. That’s harmless if the timestamps are only for display and quietly corrupting if anything orders by them — last-write-wins conflict resolution, deduplication windows, “did this happen before the cutoff” checks. When ordering matters for correctness, it needs to come from something designed to provide it — a sequence, a version number, a single authoritative source — rather than from comparing numbers that two independent machines each guessed at.
The same skew explains a class of debugging misery: correlating logs from several services during an incident and finding the timeline doesn’t make sense. Requests appear to arrive before they were sent; the downstream error is stamped earlier than the upstream call. The instinct is to doubt your understanding of the system, when the actual answer is that you’re reading two clocks that disagree. Knowing that in advance saves an hour of confusion at the exact moment an hour is expensive — and it’s another argument for the correlation identifier from the logging thread, which orders a request’s story by structure rather than by timestamp.
None of this means clocks are useless; they’re remarkably good, and for most purposes the small error doesn’t matter. The discipline is knowing which purposes those are. Display, approximate ranges, human-scale reporting: fine. Measuring durations, ordering events, deciding what happened first: not fine, and the failure is intermittent, tiny, and only visible under exactly the conditions where being wrong costs the most.