c1 w x 1 0 10 # c1 wrote x = 1 between times 0 and 10 c2 r x 1 15 20 # c2 read x and got 1 c1 cas x 1:2 ok 25 30 # compare-and-set from 1 to 2, which succeeded (or: fail) c3 w x 3 12 ? # never returned: it may or may not have happened
Consistency models lab
Watch a three-region replicated store at Cosmos DB's five consistency levels — strong, bounded staleness, session, consistent prefix, eventual — with stale and out-of-order reads, latency and availability counted as you cut regions off or fail them; the four session guarantees and causality, each broken and fixed; a linearizability and sequential-consistency checker for your own histories; and a clickable map of the models.
Added
Works with
- Isolation lab Databases and streamingthe transaction side of the same map — write skew, snapshot isolation and serializable, step by step on PostgreSQL and MySQL
- Partitioning and replication Distributed systemsleaderless Dynamo-style replication, where N, R and W choose between stale and fresh reads
- Clocks, CRDTs and gossip Distributed systemsvector and hybrid clocks behind causal consistency, and CRDTs for stores that accept writes everywhere
- Raft and Paxos, simulated Distributed systemshow a single log is agreed — the consensus that strong consistency rests on
- NoSQL data modelling Databases and streamingwhich access patterns can live with which level when you model the data
- System design interviews Interview prepa Dynamo-style key-value store as an interview design, where quorums meet hinted handoff and anti-entropy
How to use it
What does a replicated database promise when it says consistent? This page answers with things you can watch and check. Five levels is an animated store spread over three regions, with one write region, run at each of the five levels Azure Cosmos DB offers (Microsoft’s description), so you can see what each costs in latency and availability and what a reader may see. Session guarantees breaks and repairs read your writes, monotonic reads, monotonic writes, writes follow reads and causality one at a time. The History checker tells you whether a concurrent history of reads and writes is linearizable or sequentially consistent, and if not, shows the smallest part that proves it. The Map of models draws how the models relate. Everything runs in the page.
How to use it
Five levels. Pick a scenario and press Start: each step does something — a write, a read, a
partition, a failover — plays until it has happened and pauses so you can read what happened and
why, with links to the sources. Next step, Back (the simulator is deterministic, so it replays),
Restart, Play / Pause, Step ⇥ and ⏭; space plays and pauses, → is the next step. Speed
scales time (1× is a quarter of a simulated second per real second) and Hop time is how long a
message takes to cross the diagram. ⛶ Full screen (or f) gives the diagram the whole window.
-
The diagram. Three regions — West Europe, East US and Southeast Asia — each with a client and two replicas. The region with the accent border is the write region: every write goes to its leader, which gives it the next log sequence number (LSN) and copies it to every other replica. A replica card shows the LSN it has applied in order, how many versions it is behind, its values of
xandy, and badges: gap (it applied a later write before an earlier one — eventual only), waiting (it holds a write until the one before it arrives) and prep (a strong write it has prepared but not yet seen committed). A client card shows its last result, its session token at session level, and in red what was wrong with its last read. -
Do something. Change the level at any moment; read or write from any client; read
xandytogether; cut a region off, fail it, restore it, make another region the write region (a failover); heal the network; switch on a random workload. Tap a client, replica or region on the diagram for the same actions and a few more (pin a read to one replica, delay the next copy to one). -
The counters judge every read when it returns: stale (older than a write acknowledged before the read began), went backwards (older than something the same client read before), missed own write, missed a cause (older than a write that came before one the client had already seen), saw a gap, and operations that failed. Latency is shown as p50 and p99 for reads and writes, and acknowledged writes lost in a failover are counted.
-
Operations lists the latest operations with the replica that served each; Check this run in the history checker sends the whole run there. Replicas shows every replica’s log position; The levels compares what each level promises.
-
Settings: the starting level, the bound K and T for bounded staleness, the distance between regions, random delay, how long a session replica waits before handing a read to the write region, the client timeout, the write region and the seed.
Session guarantees is the same store with scenarios for each guarantee: the anomaly at a weak level, then the same steps at session level and what the session token changes.
History checker. Type or paste a history, one operation per line —
client op key value invoke return:
or pick an example, or generate a random history (from a register that really is linearizable, with a share of its reads made stale). The page says whether the history is linearizable and whether it is sequentially consistent, draws it as one row per client with each operation as a bar from invoke to return, and either numbers the operations in a valid order with the instant each one takes effect, or outlines in red a smallest set of operations that cannot be ordered, with the reason in words.
Map of models. Tap a model to see what it promises, what it implies and what implies it, whether it can stay available during a network partition, how it maps to Cosmos DB, and a link to watch it in the simulator or the checker.
What it models
-
The store follows Cosmos DB with a single write region (consistency levels, latency and throughput): writes go to one region, which orders them; other regions replicate asynchronously.
-
Strong: the write region sends prepare to every replica in every region and commits when all have confirmed; a read asks both replicas in its region and waits for any write it has prepared. Reads are refused when a region has not heard from the write region within a lease. The simulator’s own histories at strong pass the linearizability checker (Herlihy & Wing 1990).
-
Bounded staleness: the write region holds back a write that would leave any region more than K versions or T milliseconds behind what it has acknowledged; reads ask both local replicas and take the newer; replicas refuse reads when they have not heard from the write region for T.
-
Session: each acknowledgement carries the write’s LSN; the client keeps the highest LSN it has written or read as its session token and sends it with each read; a replica behind the token waits, then hands the read to the write region. Writes carry a per-session sequence number and are applied in that order. These are the four guarantees of Terry et al. 1994.
-
Consistent prefix: replicas apply the log strictly in order; a read asks one replica.
-
Eventual: replicas apply writes as they arrive; a read asks one replica.
-
-
The checker tests linearizability by the search of Wing & Gong (1993): repeatedly choose an operation that can go next — one invoked before every unchosen operation has returned — whose observed result fits the register, and backtrack; with Lowe’s (2017) memoisation of (operations chosen, register value) so equivalent states are searched once, as in Porcupine. Each key is checked on its own, which is sound because linearizability is local (Herlihy & Wing, Theorem 1). An operation that never returned may be placed anywhere after its invoke or left out. Sequential consistency (Lamport 1979) is not local, so it is checked over all keys at once by a memoised search over how far each client has got. A smallest failing set is found by dropping operations one at a time (a write together with the reads that saw its value) while the rest still fails, so removing any one more operation makes it pass.
-
The map is drawn for this page; its structure follows Viotti & Vukolić (2016) and Jepsen’s map of consistency models, and the availability classes follow Bailis et al., Highly Available Transactions (2013). Latency against consistency is Abadi’s PACELC: during a partition, choose availability or consistency; else, latency or consistency.
Limits
-
One write region only. Cosmos DB can also accept writes in every region, where conflicts are resolved by last-writer-wins or a custom procedure, and strong consistency is not offered; that is not simulated (the clocks and CRDTs tool covers merging concurrent writes).
-
Each region has two replicas; real Cosmos DB partitions hold four per region and use quorums within the region, and strong consistency there uses a dynamic quorum that can leave an unreachable region out. Here a strong write needs every replica, so any partition stops writes.
-
Latencies are fixed one-way times with optional random delay — no queueing, no request units, no throttling other than the staleness bound. The numbers are illustrative, not measurements of Azure.
-
A failover is instant and manual; a region that comes back copies the write region’s state, discarding writes that never left it.
-
The checker handles read, write and compare-and-set registers. It gives up after two million search states (shown as "?"); histories of a few hundred operations per key are fine unless they are very concurrent. Transactions are not checked: for write skew and the isolation levels, use the isolation lab.
-
Stale, non-monotonic and causal verdicts in the simulator are judged against the write region’s log, which a real client could not see — that is what makes them useful for teaching.
Linking to an example
Links can be written by hand. Add a tab after #: sim (the default), sessions, checker or
models. 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 simulator (lists below) |
|
|
A Five levels scenario, without clearing your settings |
|
|
Open that scenario at this step |
|
|
A Session guarantees scenario |
|
|
Open it at this step |
|
|
Starting level: |
|
|
Bounded staleness: versions, 1–100 |
|
|
Bounded staleness: milliseconds, 50–20000 |
|
|
Distance between regions, % of the default latencies |
|
|
Extra random delay between regions, ms |
|
|
How long a session replica waits before forwarding, ms |
|
|
Client timeout, ms |
|
|
|
|
|
An example history in the checker (list below; add |
|
|
The model selected on the map (add |
|
|
Random seed |
|
|
Playback speed: |
|
|
Hop time in seconds, or |
|
Five levels scenarios:
example= |
Shows |
|---|---|
|
Eventual against strong: a stale read from far away, and what strong costs (open) |
|
A reply seen without its post at eventual; consistent prefix holds it back (open) |
|
Bounded staleness: writes held back and reads refused while a region is cut off (open) |
|
Strong in a partition: writes fail, the cut-off region cannot read (open) |
|
The write region fails; an acknowledged write is lost at eventual, not at strong (open) |
|
A random workload and no script (open) |
Session guarantees scenarios (add #sessions):
example= |
Shows |
|---|---|
|
Read your writes (open) |
|
Monotonic reads across two replicas (open) |
|
Two writes reordered in the network (open) |
|
A reply seen without the post it answers (open) |
|
A causal chain through three clients (open) |
|
No script (open) |
Example histories (history=, add #checker): stale-read, new-old, non-monotonic,
sc-not-lin, real-time, causal, lost-update, concurrent-ok, indeterminate.
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.