Coin or account model
In the account model a payment changes a stored balance. In the coin model it creates an unspent output, and a balance is the sum of outputs. 4,000 payments/s to one account stop near 2,500 updates/s on one row, and separate outputs do not wait for each other.
See it on the board
The same traffic runs on two boards. The simulator measured both when this page was built.
| Measure | Goal | One balance row for the merchant | Outputs spread over many rows |
|---|---|---|---|
| p99 latency (Payments) | under 100 ms | 10.1 s Fail | 26 ms Pass |
| Error rate (Payments) | under 0.1% | 79% Fail | 0% Pass |
| Data age | under 5 s | 0 ms Pass | 1 s Pass |
| Monthly cost | 16 USD/mo | 16 USD/mo |
Key numbers
| Number | Value |
|---|---|
| Writes per second, one database vCPU | 2,500 writes/s |
| Entries per second, one ledger | 15,000 ops/s |
| Disk sync time for one commit | 0.4 ms |
Coin model · writes that wait for one row: 0 more each second
How it works
Two models can hold the same money. In the account model each owner has a balance in a row. A payment reads the row, adds the amount and writes it back. In the coin model each payment creates a new output, a record of an amount that can be spent once. A balance is the sum of the owner's unspent outputs.
The models behave differently under load. In the mini board card payments settle into one merchant at 4,000 payments/s, and payments need p99 below 100 ms. In the account model all of them update one balance row. A row takes one update at a time, so it stops near 2,500 updates/s, and the queue grows.
In the coin model each payment writes a new row. The writes spread over many rows and partitions, and they do not wait for each other. The merchant still needs a balance: it reads the sum of its outputs, and the sum can be a few seconds old. The mini board accepts a balance that is no older than 5 s, and it computes it in the background.
The coin model has costs. A balance read needs a sum, and spending needs to pick outputs and make change. The account model is simpler for the user and for the code.
An account can also be sharded into many sub-balances, which brings back the same effect.
In the levels you choose the model from the hot account and the read needs.