Skip to content

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

Terminal window
# 1. Start the cluster
docker compose up -d --build
docker 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 5
wait
# 3. Audit
./audit.sh

Expected results

Total balance: $1000000.00
Transfers done: <thousands>
Balance range: $XXX.XX ... $XXXXX.XX
Negative accts: 0
RESULT: PASS
The money quote:
SUM(balance) = $1000000.00
Zero 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

Terminal window
docker compose down -v