Reference build 02 · Finance
Payments Ledger
Double-entry core with idempotent write paths and reconciliation designed in, not bolted on.
What we'd be solving.
A platform is moving money on behalf of merchants using a balance column and a payments table. Retries occasionally double-charge, month-end reconciliation is manual, and no one can reconstruct why a balance is what it is.
The approach
Four decisions that shape everything else.
- 01
Balances become derived, not stored
An append-only journal of paired debit and credit entries is the source of truth. Balances are a projection, which means any historical balance can be recomputed exactly.
- 02
Idempotency enforced by the database
A unique constraint on the idempotency key, inside the same transaction as the entry write. Application-level checks lose to concurrency; a constraint does not.
- 03
Payment state modelled explicitly
Authorised, captured, settled, refunded and failed are distinct states with legal transitions, rather than booleans that can contradict each other.
- 04
Reconciliation runs on a schedule
A nightly job compares the internal journal against processor settlement reports and raises discrepancies as work items — so drift surfaces in a day, not a quarter.
What we rejected
The alternatives, and why they lost.
Anyone can list the technology they chose. What tells you whether a team can be trusted with your system is whether they can explain what they didn't choose.
Keeping a mutable balance column with row locks
Correct under load, but it discards history. When a balance is disputed there is nothing to reconstruct it from.
Event sourcing the entire domain
Right for the ledger, needless complexity for everything else. Scoping immutability to where it pays keeps the rest of the system ordinary.
Handling raw card data to reduce processor fees
It expands PCI scope across the whole platform. The saving is far smaller than the cost of the audit surface.
Other reference builds
Keep reading.
Start here
Tell us the problem.
We'll be honest about the fit.
A first conversation costs nothing and is useful even if you go elsewhere — you'll leave with an architecture opinion and a realistic sense of scope.
- Reply within 24 hours
- No sales sequence