Skip to content
~100s Visual Explainer

Lamport Clock

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

Clocks Don't Agree in Distributed Systems Process A 10:00:01 Process B 10:00:03 message Which event happened first? 2ms difference — but who's right? Forget Wall Clocks — Use Counters Process A 0 Process B 0 Lamport Clock = Simple Integer Counter Only care about causality, not real time If A causes B, then clock(A) < clock(B) Increment, Attach, Max+1 Rule 1 Local Event counter++ Rule 2 Send Message attach counter Rule 3 Receive max(loc,rcv)+1 A 1 2 B [2] 3 max(0,2)+1 Local event Send message Receive (max+1) Watch the Clocks Tick A 1 2 4 B 3 4 5 [2] max(0,2)+1=3 Send at t=2 → Receive at t=3 → Causal order preserved! Causality Goes One Way A B 3 3 No message ? The Limitation clock(A) < clock(B) A might have caused B clock(A) = clock(B) Concurrent (no order) ⚠ Cannot detect all concurrent events Same clock doesn't prove causation → Vector Clocks solve this (one counter per process)
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 performs a local event (clock goes to 1), then sends a message (clock goes to 2). Process B, with clock at 0, receives the message with timestamp 2. It calculates max(0, 2) + 1 = 3.

Now any event after the receive on B has clock > 2, preserving the ordering: send happened before receive.

  • Send is an event itself: A's clock becomes 2
  • Receive calculates max(local, msg)+1 = 3
  • Causal chain: send → receive maintained
  • B's subsequent events continue from 3

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)

What's Next?

Now that you understand Lamport clocks, explore related concepts: Eventual Consistency relies on logical ordering for conflict resolution, and Distributed Systems covers the broader context. For full concurrency detection, look into vector clocks.