Read this as What ordering can you prove without synchronized clocks?
- Failure Trap
- Confusing logical time with wall-clock time or global simultaneity.
- Decision Rule
- Use Lamport clocks for happens-before reasoning; use extra tie-breakers or vector clocks when concurrency matters.
Clocks Don't Agree in Distributed Systems
Physical clocks on different machines drift apart. Even with NTP synchronization, clocks can differ by milliseconds — enough to mis-order events. Two processes might each think their event happened first.
We need a way to order events that doesn't rely on physical time.
- Clock drift is inevitable (different crystal frequencies)
- NTP helps but doesn't guarantee perfect sync
- Network delays add uncertainty
- Need logical ordering, not physical timestamps
Forget Wall Clocks — Use Counters
Leslie Lamport's insight (1978): We don't need to know the actual time. We only need to know which events could have caused which other events — the "happens-before" relation.
A simple integer counter per process is enough to capture causality.
- Lamport clock: Integer counter starting at 0
- Each process maintains its own counter
- Counter only increases (never decreases)
- Captures the "happens-before" relationship
Increment, Attach, Max+1
The Lamport clock algorithm has three simple rules:
- Rule 1 — Local event: Increment your counter before each event
- Rule 2 — Send message: Attach your current counter value
- Rule 3 — Receive message: Set counter to
max(local, received) + 1
These rules ensure that if event A causally precedes event B, then clock(A) < clock(B).
Watch the Clocks Tick
Process A ticks through three events: a local event (clock 1), a send
(clock 2), then another local event (clock 3 — Rule 1 just increments,
so 2 becomes 3). Process B, starting at 0, receives the message stamped
2 and calculates max(0, 2) + 1 = 3. B's next local event
ticks to 4.
Because the send (2) is lower than the receive (3), the ordering holds: send happened before receive.
- A reads 1, 2, 3 — each local event just adds one (Rule 1)
- The send carries timestamp 2 across to B
- B's receive computes max(local, msg) + 1 = 3 (Rule 3)
- B's next local event continues to 4
Causality Goes One Way
Lamport clocks have a key limitation: if clock(A) < clock(B), we only know A might have caused B. We cannot conclude A definitely caused B — they might be concurrent (causally independent).
-
clock(A) < clock(B)→ A happened-before B OR concurrent clock(A) = clock(B)→ definitely concurrent- Cannot distinguish causation from coincidence
- Vector clocks solve this (one counter per process)