Two servers in the same rack, bought on the same day, running the same software, will disagree about what time it is — and the gap grows every hour you leave them alone. It is not a bug; it is physics. A computer's clock is a tiny quartz crystal oscillating at a nominal frequency, and no two crystals oscillate at exactly the same rate. One machine's "one second" is fractionally longer than another's, so their readings drift apart, silently, forever.
In a single computer this rarely matters. In a
Precision here demands two distinct words that beginners blur together.
The relationship is exactly like position and velocity: skew is where the clocks are now; drift is how fast the skew is changing. You can zero the skew by setting both clocks equal — but if they drift, the skew reopens immediately. That is why synchronisation is never "set it once": it must repeat forever, nudging clocks back before drift pulls them apart again. A typical quartz clock drifts tens of ppm; left unsynchronised for a month it can be off by minutes.
The obvious fix: ask a machine that has the accurate time (say, one with a GPS or atomic clock) "what time is it?" and set your clock to the reply. The catch is the network delay: by the time the answer reaches you, it is already stale by however long the trip took. Cristian's algorithm (1989) corrects for this with a beautifully simple estimate.
The whole round trip took
The error is bounded by half the round-trip time (the trip could have been lopsided), so the shorter and more symmetric the path, the better the estimate. This "measure the round trip, assume it split evenly" idea is the seed of every time-sync protocol, including NTP.
Cristian's assumes there is an authoritative clock. The Berkeley algorithm (1989) takes the opposite stance: no machine's clock is trusted more than any other's; agree on the average. It is used when you just want a set of machines to agree with each other, even if none of them has the "true" time.
Sending adjustments rather than absolute times matters: it lets clocks be slewed gradually (nudged faster or slower) rather than jumped, which avoids a clock ever going backwards — a jump backward can make a later event appear to happen before an earlier one, breaking any code that assumes time moves forward. Berkeley is internal synchronisation (agree with each other); Cristian's and NTP are external (agree with a reference).
The Network Time Protocol (NTP) is Cristian's idea, industrialised and running on essentially every connected device on Earth. Its two big ideas are a hierarchy of sources and a four-timestamp exchange that separates offset from delay.
Time flows down a tree of strata:
A higher stratum number means "further from the true source," and NTP prefers lower-stratum, lower-delay peers. The hierarchy keeps the whole Internet's clocks anchored to a handful of atomic references without everyone hammering the same few servers.
The four timestamps are collected on one request/reply:
From these, NTP computes two quantities. The round-trip delay subtracts out the time
the server spent processing (
And the clock offset — how far ahead (or behind) the client is relative to the server — is the average of the two apparent one-way differences:
The genius is the averaging: if the network delay is symmetric, the errors on the "up" trip and
the "down" trip cancel, leaving a clean estimate of the true offset regardless of how long the trip took.
The client then slews its clock by
NTP repeats this exchange with several peers, filters out samples with high delay (they carry more error), and disciplines the local clock continuously — steering its frequency to fight drift, not just correcting the offset once. Over the public Internet it typically keeps machines within a few milliseconds of true time; on a local network, well under a millisecond.
Here is the twist that surprises everyone. Suppose you spend all that effort and get every machine's clock agreeing to within, say, one millisecond. Can you now stamp each event with the wall-clock time and sort them to recover the true order they happened in? No — and this is fundamental, not a tuning problem.
The reason: synchronisation leaves a residual uncertainty (the offset estimate is never exact, and delay is never perfectly symmetric). If two events on two machines happen closer together in time than that uncertainty, their timestamps cannot tell you which truly came first. Worse, an event on machine A that caused an event on machine B could carry a later wall-clock timestamp than the effect, purely because A's clock was running a hair fast. You would conclude the effect preceded its cause.
The classic, costly mistake: "our clocks are synced by NTP, so I'll just compare timestamps to decide which write happened first." Do not do this. NTP gives you clocks that agree approximately, not clocks that are identical. There is always a residual skew of milliseconds (sometimes much more after a network hiccup), and any two events that fall inside that window can be ordered backwards by their timestamps — including a cause appearing to follow its effect.
Real systems have lost data this way: a "last-write-wins" conflict resolver that trusts wall-clock
timestamps will silently discard the newer write whenever the writer's clock happened to run
slow. To order events by causality — "did X happen before Y in a way that could matter?" —
you need
Google's Spanner database confronts the ordering problem head-on with a service called
TrueTime. Instead of pretending its clocks are exact, TrueTime embraces the
uncertainty: every time query returns an interval
The trick is what Spanner does with that interval: to commit a transaction at time