Store the ledger, not the balance

A balance is a cache. Treat it like one and reconciliation stops being a monthly panic.

Sample article5 min readSquad 01
01

Balances lie

A balance column updated in place has no memory. When it is wrong, and it will be, there is nothing to replay. An append-only ledger of entries can be summed at any point in time and audited line by line.

02

Double entry is not optional

Every movement debits one account and credits another, in one transaction. The books always balance because the schema makes it impossible for them not to.

Illustrative excerpt
select account_id, sum(amount) as balance
from ledger_entries
where posted_at <= $1
group by account_id;
03

Then cache

Materialise balances for speed if you need to, but derive them from the ledger and rebuild them when they disagree. The ledger is the truth. The balance is a convenience.

Sample article. Written to show the register, not to claim the result.

More on payments.

  1. 01

    Designing webhooks that survive retries

    Providers retry. Networks drop. Your handler will run twice. Build for it on day one, not after the first double charge.

    Payments7 min readSquad 01

Next article.

Payments

7 min readDesigning webhooks that survive retriesRead the article

Got something complicated?

Tell us what you're building. You'll hear back from an engineer, not a sales team.