Lamport Clock

Understanding logical time — how distributed systems order events without synchronized clocks.

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.
Lamport logical clock walkthrough A five-step explainer. Wall clocks on two processes disagree, so each process keeps an integer counter instead. Three rules govern it: increment on a local event, attach the counter when sending, and on receive set the counter to max(local, received) plus one. A worked run shows process A ticking 1, 2, 3 and process B receiving at 3 then ticking to 4. Equal clocks only mean events may be concurrent, which is the clock's limitation. Wall Clocks Disagree Process A 10:00:01 Process B 10:00:03 Which event was first? 2 seconds apart — but whose clock is right? Use Counters Instead Process A 0 Process B 0 A Lamport clock is just an integer. Track causality, not real time. Three Rules 1 · Local event counter++ 2 · Send message attach counter 3 · Receive max(loc, recv) + 1 If A causes B, then clock(A) < clock(B) Watch It Tick A 1 2 3 B 3 4 [2] max(0, 2) + 1 = 3 Send (2) precedes receive (3). Causal order is preserved. Causality Goes One Way A 3 B 3 No message between them ? Same clock ≠ same event. Equal counters mean events may be concurrent. Vector clocks fix this.
1 / ?

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)