Free preview

Approach 6: Logical Clocks

Why this matters: logical clocks sidestep the clock problem entirely — no synchronization, no drift, no NTP. The cost is size, and watching that cost collide with the 64-bit budget is the lesson.

Key takeaway

Logical clocks — Lamport clocks and vector clocks — rely on monotonically increasing counters rather than wall-clock time. They cannot drift because they are not measuring anything physical.

Lamport clocks

Lamport clocks establish a partial ordering of events. The algorithm is small:

1. Each process keeps a counter, initialized to zero.
2. Increment the counter before every local event.
3. When sending a message, include the current counter as a timestamp.
4. On receiving a message, set the clock to:
       max(local clock, received timestamp) + 1
   before recording the receipt event.

This guarantees that if event a causally precedes event b, the timestamp of a is less than that of b.

Lamport clocks provide a partial ordering consistent with the happened-before relationship. A total order can be derived by breaking ties with node or process identifiers, though the resulting order depends on the identifier assignment you chose.

Vector clocks

Vector clocks maintain causal history — they capture happened-before relationships between events. Each node tracks a counter per node, so the full dependency structure is visible.

The chapter's proposed ID layout:

 1 bit      53 bits              10 bits
[sign]     [vector clock]       [worker]

 1 + 53 + 10 = 64 bits
FieldBitsPurpose
Sign bit1Always zero
Vector clock53The counters of each node
Worker number102^10 = 1,024 worker IDs

The ID pattern is [vector-clock][worker-id]. Following three nodes A, B, and C in a data center:

Start:                A = [0,0,0]   B = [0,0,0]   C = [0,0,0]

Event A1 on node A:   A = [1,0,0]   ->  ID: [1,0,0][A]
Event C1 on node C:   C = [0,0,1]   ->  ID: [0,0,1][C]
Event B1 on node B,
  having seen A1:     B = [1,1,0]   ->  ID: [1,1,0][B]

Read B = [1,1,0]: node B knows about one event from A and one of its own, and nothing from C. That single vector encodes B's entire causal history — which is exactly what Lamport's scalar counter could not do.

Why vector clocks don't fit

Vector clocks capture full causal history but require a vector size of n, where n is the number of nodes. In large systems — or systems where every client (a web browser, say) is a node — the storage and bandwidth requirements become prohibitive.

Scorecard

UniqueScalableAvailable64-bit numeric IDCausality maintained
Using a range handler
Using Twitter Snowflakeweak
Using vector clocksweakcan exceed

The first approach to fully satisfy causality — and it pays for that with the size and scalability columns.

Key takeaway

Lamport clocks are compact and give only a partial order you cannot invert. Vector clocks give true causality and grow with the cluster. Neither fits a fixed 64-bit budget at scale — which sends us back to physical time, done properly.

Interview signal by level

LevelWhat a strong answer sounds like
L4"Logical clocks use counters instead of real time."
L5Distinguishes them: "Lamport gives a partial order; vector clocks track a counter per node so you can actually detect concurrency."
Staff+Names the asymmetry and the size wall: "with Lamport, a-before-b implies L(a) < L(b) but not the converse — so it can't prove causality. Vector clocks can, but they're O(n) in cluster size, which blows a fixed 64-bit budget the moment n is large or every client is a node."

Next: what happens if you buy better clocks.

Enjoying the preview?

Create a free account to unlock the rest of this course, the in-browser judge, and live AI mock interviews.

Sign up free to continue