Demo 3: The Auditor's Demo (Bank Ledger)
Demo 3: The Auditor’s Demo (Bank Ledger)
A financial integrity stress test. 20 concurrent workers perform random bank transfers while the primary database is killed and restarted 5 times. At the end, a single query proves that not a single cent was lost.
What invariant is tested?
Every transfer is a paired DEBIT + CREDIT inside a single transaction. The total balance across all 100 accounts must always equal exactly $1,000,000.00 — the original seed amount. If any transaction is partially applied, double-applied, or lost during failover, this number will be wrong.
How to run
# 1. Start the clusterdocker compose up -d --builddocker compose exec pg-primary psql -U app -d bankdb -f /dev/stdin < schema.sql
# 2. Run workers and chaos in parallel./workers.sh 20 120 &./chaos.sh 5wait
# 3. Audit./audit.shExpected results
Total balance: $1000000.00Transfers done: <thousands>Balance range: $XXX.XX ... $XXXXX.XXNegative accts: 0
RESULT: PASS
The money quote:SUM(balance) = $1000000.00Zero cents lost across all failovers.HeliosProxy’s Transaction Replay records every statement in the active transaction,
along with a digest of the responses the client was shown. When the primary dies
mid-transaction (tr_mode = "transaction"), the proxy detects the failure, waits for
the new primary, and replays the exact sequence of statements there — the client sees
a pause, not a dropped connection, and the DEBIT+CREDIT pair stays atomic. Each
replayed response is re-digested and compared: if the new primary would have returned
anything other than what the client already saw, the replay is rolled back and the
statement returns 40001 rather than continuing on different rows. A transaction
opened at SERIALIZABLE or REPEATABLE READ is never replayed at all. If the primary
dies while a
COMMIT is outstanding, that COMMIT is never retried: the client receives
SQLSTATE 08007 and the transfer must be verified before it is re-issued. That
is what keeps the ledger free of double-applied transfers.
Configuration
- Workers: 20 concurrent (configurable:
./workers.sh 50 180) - Chaos cycles: 5 kills (configurable:
./chaos.sh 10) - Transfer amount: random $1-$500 per transfer
- Pool mode: transaction
- Sync replication: enabled (synchronous_standby_names = ’*‘)
Cleanup
docker compose down -v