Double-entry ledger

Double entry records each transfer as a debit and a credit that sum to 0. A balance is the sum of its entries, so you can rebuild and check it at any time. A cached balance that lives for 300 s can stay wrong for 5 minutes.

Play a level

See it on the board

The same traffic runs on two boards. The simulator measured both when this page was built.

Board to show
SQLHTTP/2SQLPartner appsUsersPostgres1 vCPU · 2 GBRedis cache1 vCPU · 1 GB
SQLHTTP/2SQLPartner appsUsersPostgres1 vCPU · 2 GBRedis cache1 vCPU · 1 GB
Cache keeps old balances for 300 s: misses a goal
HTTP/2SQLgRPCPartner appsUsersPostgres1 vCPU · 2 GBRedis cache1 vCPU · 1 GBChange capt…1 vCPU · 1 GB
SQLHTTP/2SQLgRPCPartner appsUsersPostgres1 vCPU · 2 GBRedis cache1 vCPU · 1 GBChange capt…1 vCPU · 1 GB
Ledger changes update the cache: meets the goals
See it on the board
Measure Goal Cache keeps old balances for 300 s Ledger changes update the cache
Data mismatches (Balances) under 2,500 199,108 Fail 1,813 Pass
p99 latency (Balances) under 50 ms 23 ms Pass 24 ms Pass
Error rate (Balances) under 0.1% 0% Pass 0% Pass
Monthly cost 24 USD/mo 28 USD/mo

Key numbers

Default part values from the catalog. The mini board has 400 transfers/s and 8,000 balance reads/s.
NumberValue
Entries per second, one ledger15,000 ops/s
Ledger write, median0.5 ms
Default checkpoint interval of a change feed30 s
An order and its event commit togetherTap to turn the outbox on or off

Outbox · 10 orders · 10 events · 0 lost

How it works

Money does not appear or vanish. A transfer moves value from one account to another. A double-entry ledger records this as two entries: a debit on one account and a credit on the other. The two entries are written together in one transaction, and they always sum to zero. If they do not, something is wrong, and the ledger can say so.

A balance is not a stored fact. It is the sum of the entries of the account. This helps in two ways. You can rebuild any balance from the entries and compare it with the stored value. And you never overwrite history: a mistake is fixed with a new pair of entries, not by changing an old one.

In the mini board 400 transfers/s post to the ledger, and a wallet reads 8,000 balances/s through a cache that keeps entries for 300 s. A cached balance can stay wrong for 5 minutes after a transfer. The run counts the reads that do not match the ledger.

The cache needs the changes. A change feed reads each new ledger entry and updates the cached balance within a short time. Then the cache is fast and still right, and the number of mismatched reads falls below the limit of 2,500.

Keep the total of all entries as a control. It must always be zero.

In the levels you send ledger changes to the cache and check the mismatched reads.