TodoMVCC

Demo Spec PostgreSQL XTDB

TodoMVCC = like TodoMVC but for databases (not UIs!)

Developers building data-intensive applications often struggle with versioning, concurrency control, and maintaining consistency over time. Manual versioning schemes, transaction anomalies, and locking contention plague traditional approaches.

This project demonstrates these challenges using everyone's favorite example: a todo list.


The Problem

Building reliable applications often means wrestling with:

What if there was a better way?


Why SERIALIZABLE Matters

Most applications run on READ COMMITTED isolation by default, which allows various consistency anomalies. Let's see how these manifest in a simple todo app:

🐛 Lost Update Example

Two users editing the same todo simultaneously:

-- User A starts editing todo #123
BEGIN;
SELECT title FROM todos WHERE id = 123;  -- "Buy groceries"

-- User B also starts editing the same todo
BEGIN;
SELECT title FROM todos WHERE id = 123;  -- "Buy groceries"

-- User A updates the title
UPDATE todos SET title = 'Buy groceries and milk' WHERE id = 123;
COMMIT;

-- User B updates based on stale data
UPDATE todos SET title = 'Buy groceries and bread' WHERE id = 123;
COMMIT;

-- Result: User A's changes are lost!

In READ COMMITTED: User B's update overwrites User A's changes.

In SERIALIZABLE: One transaction would be aborted and retry with fresh data.

📊 Write Skew Example

Maintaining a business constraint across multiple todos:

-- Rule: At most 3 todos can be marked "urgent" priority
-- Currently 2 urgent todos exist

-- Transaction A: Mark todo #456 as urgent
BEGIN;
SELECT COUNT(*) FROM todos WHERE priority = 'urgent';  -- Returns 2
-- User thinks: "OK, I can add one more"
UPDATE todos SET priority = 'urgent' WHERE id = 456;

-- Transaction B: Mark todo #789 as urgent
BEGIN;
SELECT COUNT(*) FROM todos WHERE priority = 'urgent';  -- Returns 2
-- User thinks: "OK, I can add one more"
UPDATE todos SET priority = 'urgent' WHERE id = 789;

-- Both transactions commit successfully
-- Result: 4 urgent todos! Business rule violated.

In READ COMMITTED: Both transactions see consistent snapshots but create inconsistent final state.

In SERIALIZABLE: One transaction would be aborted to maintain the constraint.

SERIALIZABLE isolation eliminates these anomalies by ensuring transactions appear to execute one at a time, even when running concurrently. For todo apps, this means:

📚 Learn More About Consistency

For a deep dive into consistency models and isolation levels, check out Jepsen's Consistency Models - an excellent interactive guide to understanding how different databases handle consistency.

Key resources:


Two Approaches

🐘 Traditional SQL (PostgreSQL)

Manual versioning with locking-based concurrency control.

Characteristics:

Example Schema:

CREATE TABLE todos (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    title TEXT NOT NULL,
    completed BOOLEAN NOT NULL DEFAULT false,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    version BIGINT NOT NULL DEFAULT 1
);

CREATE TABLE todos_history (
    id UUID NOT NULL,
    title TEXT NOT NULL,
    completed BOOLEAN NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    version BIGINT NOT NULL,
    txid BIGINT NOT NULL DEFAULT txid_current(),
    PRIMARY KEY (id, version)
);

📖 View Complete PostgreSQL Example →

🔥 XTDB Bitemporal

Built-in time dimensions with optimistic concurrency control.

Characteristics:

Example Query:

-- Time travel query (built-in)
SELECT * FROM todos
FOR SYSTEM_TIME AS OF '2024-01-01T12:00:00Z'
WHERE completed = false;

-- No manual versioning needed!
INSERT INTO todos (id, title, completed)
VALUES (1, 'Learn XTDB', false);

XTDB implementation coming soon...


Interactive Demo

The demo will showcase side-by-side comparisons demonstrating:

  1. Creating todos with different effective dates
  2. Concurrent updates to the same todo item
  3. Historical queries to see past states
  4. Transaction isolation behavior under load
  5. Manual versioning vs automatic bitemporal tracking

🚧 Interactive demo coming soon...


Real-World Impact

Challenge Traditional SQL XTDB Bitemporal
Version Tracking Complex application logic Zero application code
Concurrency Deadlocks and timeouts No locks, no contention
Consistency Race conditions possible Perfect isolation
Audit Trail Manual triggers/tables Built-in auditability
Performance Degradation with locking Predictable characteristics

Implementation Guide

Want to contribute an implementation? Check out the TodoMVCC Specification for guidelines on:


Educational Use

TodoMVCC is perfect for:


Built by XTDB | View on GitHub

TodoMVCC combines the familiar TodoMVC concept with Multi-Version Concurrency Control - because sometimes the best way to understand complex database concepts is through a simple, relatable example that every developer knows: a todo list.