Double-entry ledger engine · Go

Money that can't go missing.

A single-writer state machine posts every transfer as a balanced debit and credit, guarded by idempotency keys and a write-ahead log. Concurrent payments and retried requests, the two things that quietly corrupt naive ledgers, can't break the books.

Single-writer state machine Integer cents, no floats Idempotent retries WAL crash recovery
Σ of every balance Balanced
$0.00
The conservation law: this must be exactly zero, always. If a bug ever created or destroyed a cent, this number would move.
In circulation
$0.00
Transfers
0

Ledger

0 accounts
AccountBalance
Open account
Deposit
Transfer

How it stays correct

Single-writer
One goroutine owns every balance, so there are no data races and no locks to get wrong, and the command order is deterministic.
Double-entry · integer cents
Each transfer debits and credits by the same amount in whole cents, so the ledger always sums to zero. Never floats.
Idempotency keys
A retried payment carries a key; the engine returns the first result and never charges twice.
Write-ahead log · group commit
Every command is fsync'd before it is acknowledged, batched so one fsync covers many transfers, about 13x faster than fsync-under-a-lock. After a crash, state rebuilds by replaying the log.

The experiment proof

500k transfers · 16 workers

One concurrent workload, three ledgers: a naive version with no synchronization, a correct global-mutex version, and Tally's single-writer engine. The naive run shows why synchronization isn't optional. The other two are both correct, so the real comparison is the cost of how each one serializes.