Clocks, CRDTs and gossip
Time and agreement without coordination: space-time diagrams with Lamport, vector and hybrid logical clocks (skewed and drifting physical clocks, last-writer-wins gone wrong, causal broadcast); CRDTs from G-Counter to OR-Set and a collaborative RGA text editor across three replicas; and SWIM failure detection and epidemic gossip, animated.
Added
Works with
- Offline-first sync and replication Distributed systemsrevision-tree sync (CouchDB, PouchDB) keeps concurrent edits as conflicts for the app to resolve, where CRDTs merge them
- Consistency models lab Distributed systemswhat causal and session consistency guarantee to clients, shown on a multi-region store
- Distributed patterns on Redis Databases and streamingleases, locks and token buckets that depend on clocks, and what skew and process pauses do to them
- System design interviews Interview prepcollaborative editing (OT against CRDTs), per-conversation ordering in group chat and unique ID generators, as interview designs
How to use it
Three things distributed systems do without a coordinator — order events, merge concurrent updates, and agree on who is alive — each as something you can play with in this page. Nothing here talks to a real system.
How to use it
The Clocks and Gossip & SWIM tabs are simulators. Pick a scenario and press Start. Each step
does something, plays until it has happened and pauses so you can read what happened and why, with
links to the papers. Next step moves on, Back rewinds (the simulator is deterministic, so it
replays the earlier steps), ⏭ jumps to the end of the step and Step ⇥ advances to the next
single event. Space plays and pauses; → is the next step. Each tab has a playground with no
script. Speed scales everything (at 1× a quarter of a simulated second per real second); Hop
time is how long a message takes to cross the diagram at 1× — while one is on its way the
simulated clock slows down — and Sim clock turns that off. Neither changes what happens. ⛶ Full
screen (or f) gives the diagram the whole window with the narration in a side column you can
hide; Escape leaves.
Clocks. A space-time diagram: one line per process, true time running to the right, events as dots (grey local, blue send, green receive, orange a write), messages as arrows; a dashed amber stretch is a message held back by causal delivery. Above or below each event is its timestamp — Show picks Lamport, vector, HLC (l.c) or all three. On the left each process’s physical clock offset and drift; on the right its clocks now. Tap an event to see its causal past (amber) and future (pink); tap a second to compare: happened before or concurrent, with the Lamport, vector and HLC timestamps side by side. Tap a process, or use Do something, to add local events, writes, messages and broadcasts, shift a clock, turn causal delivery on, or slow a process’s links. Panels: Events (every timestamp, and each process’s physical clock reading), Last writer wins (which write of a key survives under physical, Lamport and HLC timestamps, and whether a causally later write was lost), HLC vs physical time (the largest l − pt seen against ε, the largest gap between two clocks).
CRDTs. Pick a type. Three replicas, A, B and C, each with its own state; the links between them can
be cut. Change any replica (increment, set, add, remove, or type in the text box for RGA), then
Sync — one gossip round: every replica merges the state of each replica it can reach — or
⇠ merge one replica into another, or tick auto-sync. Each card shows the value and the full
state (tags and tombstones included); the line below says whether the replicas have converged, and
the merge laws are checked on the current states. For text, each character’s id (Lamport counter
replica) is shown, and deleted characters stay as struck-out tombstones.
Gossip & SWIM. A group of members around a circle. Each card shows the member’s incarnation number, whom it is probing, and a row of dots: what it believes about every member (green alive, amber suspect, red dead). Messages: ping, ack, ping-req M4 (please ping M4 for me), ack M4 (relay); a +2 means two membership updates ride along. Tap a member to kill, pause (a long GC), isolate or restart it, or cut single links. Panels: every member’s view, and detection times. Below the simulator, a chart runs push, pull and push-pull rumour spreading on n nodes and compares the rounds with theory.
What it models
-
Lamport clocks (Lamport 1978): +1 per event; on receive, max(own, message) + 1. They satisfy the clock condition (a → b ⇒ L(a) < L(b)), not its converse.
-
Vector clocks (Fidge 1988, Mattern 1989): one entry per process; own entry +1 per event, element-wise max on receive. a → b exactly when V(a) < V(b).
-
Hybrid logical clocks (Kulkarni, Demirbas, Madappa, Avva and Leone, Logical Physical Clocks and Consistent Snapshots in Globally Distributed Databases, 2014, Figure 5): l = max(l, pt) on send and local events, l = max(l, lm, pt) on receive, c counting events that share an l. Physical clocks have an offset and a drift per process; the tool checks l − pt ≤ ε and e → f ⇒ hlc(e) < hlc(f).
-
Last writer wins by each timestamp, against the causal truth from vector clocks (Kleppmann, Designing Data-Intensive Applications ch. 8).
-
Causal broadcast (Birman, Schiper and Stephenson, Lightweight causal and atomic group multicast, 1991): a broadcast from j is delivered when it is j’s next one and everything its sender had delivered has been delivered here.
-
CRDTs (Shapiro, Preguiça, Baquero and Zawirski, A comprehensive study of Convergent and Commutative Replicated Data Types, INRIA RR-7506, 2011, and Conflict-free Replicated Data Types, SSS 2011): state-based G-Counter, PN-Counter, LWW-Register (ties by replica id), MV-Register (vector clocks, concurrent values kept), G-Set, 2P-Set (tombstones; removed for good) and OR-Set (unique tags; add wins over a concurrent remove). Merge is a join: commutative, associative and idempotent.
-
RGA (Roh, Jeon, Kim and Lee, Replicated abstract data types: Building blocks for collaborative applications, JPDC 2011): each element has an id (Lamport counter, replica) and the id of the element it was inserted after; siblings are ordered by descending id; deletions leave tombstones. The replicas' states merge by union, so any order of syncs converges.
-
Gossip (Demers et al., Epidemic algorithms for replicated database maintenance, 1987): push, pull and push-pull with fan-out 1 in synchronous rounds. Push informs everyone in about log2 n + ln n rounds (Pittel 1987); push-pull in log3 n + O(log log n) (Karp, Schindelhauer, Shenker and Vöcking 2000).
-
SWIM (Das, Gupta and Motivala, SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol, DSN 2002): each protocol period a member pings the next target from a shuffled list (§4.3); with no ack within the ping timeout it sends ping-req to k others, who ping the target and relay its ack (§3.1); with no ack by the end of the period the target is suspected at its incarnation number, and confirmed dead after the suspicion timeout unless an alive with a higher incarnation arrives — a suspected member that hears of it refutes by incrementing its incarnation (§4.2). Updates are piggybacked on pings and acks, each sent λ·⌈log2(n+1)⌉ times (§4.1). Lifeguard (Dadgar, Phillips and Currey 2018) — the extensions in HashiCorp’s memberlist — is described, not modelled.
Limits
-
Clocks: messages are point-to-point or broadcast to everyone; no process groups or membership. Physical clocks are linear (offset plus constant drift) with whole-millisecond readings; there is no clock synchronisation protocol and no NTP step.
-
The LWW comparison stamps each write once with each kind of timestamp; it does not simulate replicas exchanging writes.
-
CRDTs are state-based only (no operation-based delivery), on three replicas, with metadata never garbage-collected (tombstones and tags grow). LWW timestamps are a shared counter with replica B five ticks ahead. RGA edits are diffed as one changed region per keystroke batch.
-
SWIM: no join protocol beyond a restarted member announcing itself, no Lifeguard extensions (no nacks, no local health multiplier, no dynamic suspicion timeouts), no anti-entropy full state sync; the suspicion timeout is a fixed number of periods.
-
The gossip chart uses synchronous rounds and a uniformly random peer each round.
Linking to an example
Links can be written by hand. Add a tab after #: clocks (the default), crdts or swim. A
link’s settings replace this page’s saved settings (a button restores yours); a scenario brings its
own settings, and parameters given with it override them.
| Parameter | Meaning | Example |
|---|---|---|
|
A scenario from either list below |
|
|
The clocks scenario, without clearing your settings |
|
|
Open the clocks scenario at this step |
|
|
The SWIM scenario (with |
|
|
Open the SWIM scenario at this step |
|
|
Processes, 2–5 |
|
|
Message latency, ms |
|
|
Extra random latency up to this, ms |
|
|
Physical clock offset of P1, P2, P3 in ms |
|
|
Clock drift in ‰: P2 runs this much fast, P3 this much slow |
|
|
Causal delivery of broadcasts ( |
|
|
Timestamps drawn: |
|
|
SWIM members, 3–9 |
|
|
SWIM protocol period, ms |
|
|
SWIM indirect probes per failed ping |
|
|
SWIM suspicion ( |
|
|
Suspicion timeout in protocol periods |
|
|
The CRDT shown: |
|
|
Random seed (latency jitter, probe order) |
|
|
Playback speed: |
|
|
Hop time in seconds ( |
|
Clock scenarios:
example= |
Shows |
|---|---|
|
Lamport clocks: the receive rule, the clock condition, and why its converse fails (open) |
|
Vector clocks: element-wise max, happened-before, concurrency detected (open) |
|
A fast clock makes last-writer-wins lose a causally later write; HLC keeps it (open) |
|
Hybrid logical clocks in detail: the receive rule, the counter, l − pt ≤ ε with drift (open) |
|
Causal broadcast: an answer overtakes its question, then is held until it arrives (open) |
|
Processes and nothing scripted (open) |
SWIM scenarios (add #swim):
example= |
Shows |
|---|---|
|
The protocol period: pings and acks, round-robin targets, piggybacked gossip (open) |
|
A broken link: ping-req through k helpers avoids a false alarm (open) |
|
A crash: suspicion, dissemination, confirmation, detection time (open) |
|
A paused member is suspected and refutes with a higher incarnation (open) |
|
A group with no script (open) |
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.