“Physical wall clocks on independent computers suffer from clock drift and NTP synchronization skew. A Vector Clock is an array of logical clock counters maintained by each node [V_1, V_2, ... V_N]. By incrementing local counters on internal events and taking element-wise maximums on message receipt, vector clocks establish unambiguous happens-before (a -> b) causal ordering or detect concurrent conflicts.”
Why physical wall clocks drift in distributed networks, and how logical vector clocks track causal happens-before relationships.
// Vector Clock Implementation in TypeScript
class VectorClock {
public clock: Map<string, number> = new Map();
constructor(public readonly nodeId: string) {
this.clock.set(nodeId, 0);
}
increment(): void {
const current = this.clock.get(this.nodeId) || 0;
this.clock.set(this.nodeId, current + 1);
}
merge(remoteClock: Map<string, number>): void {
for (const [node, time] of remoteClock.entries()) {
const localTime = this.clock.get(node) || 0;
this.clock.set(node, Math.max(localTime, time));
}
this.increment();
}
// Returns true if this clock strictly happened before other
happensBefore(other: VectorClock): boolean {
let hasStrictlyLess = false;
for (const [node, time] of this.clock.entries()) {
const otherTime = other.clock.get(node) || 0;
if (time > otherTime) return false;
if (time < otherTime) hasStrictlyLess = true;
}
return hasStrictlyLess;
}
}Each node i initializes vector clock V_i of size N with all zeros [0, 0, 0]
Local event: Node i increments its own entry V_i[i] = V_i[i] + 1
Message send: Node i attaches current vector V_i to the network message
Message receive: Node j receives message with vector V_msg
Merge: Node j sets V_j[k] = max(V_j[k], V_msg[k]) for all k, then increments V_j[j]
Interval Tree Clocks (ITC) allow dynamic peer joining and leaving without pre-allocating fixed vector array dimensions.