Distributed systems can't trust wall clocks for ordering. NTP skew, leap seconds, VM clock drift — all real. Logical clocks (Lamport, vector) and hybrid clocks (HLC) give you correct ordering without requiring perfect time sync. Knowing which to reach for is a core skill.
Wall clocks: when they're OK and when they're not
OK for: human-readable timestamps, log timelines, rate limits with seconds-of-precision tolerance. NOT OK for: ordering events across nodes, distributed locks, MVCC commit timestamps. Skew of 100ms+ is normal in practice.
Lamport timestamps
Each event gets a counter. Send a message: include your counter. Receive: counter = max(yours, theirs) + 1. Guarantees: if A causally precedes B, then ts(A) < ts(B). Doesn't capture concurrency.
Vector clocks
Each node maintains a vector of counters, one per node. Send/receive updates the corresponding entry. Two events are concurrent iff neither vector dominates the other. Captures concurrency precisely; vector size = node count (problematic at scale).
Hybrid Logical Clocks (HLC)
Wall-clock-ish prefix + logical counter suffix. Wall-clock close to truth, monotonically advances on local events and message receipt. Used by CockroachDB, Spanner-style systems. Bounded skew + causal ordering in one stamp.
TrueTime (Spanner's hack)
Spanner uses GPS + atomic clocks in every DC to give a bounded uncertainty interval. commit_ts = now.latest(); wait out the uncertainty (<10ms) before responding. Buys external consistency. Expensive infra; nothing else has it.