Knowledge CoreFinance Engineering

Building a Double-Entry Ledger Architecture

JW
Julia Watanabe
VP of Finance Engineering
·14 min read

If you are building a marketplace, a Payment Facilitator (PayFac), or an embedded fintech platform, tracking who owes what to whom is the most mission-critical piece of code you will write. Standard CRUD databases are entirely unsuited for this. You must build an immutable, double-entry ledger.

The Core Principle: Immutability

In a strict financial ledger, `UPDATE` and `DELETE` commands do not exist. To correct an erroneous $10,000 credit, you do not update the database row to $0. You create a new compensating entry—a $10,000 debit. This ensures a forensic, mathematically provable audit trail that regulators and auditors demand.

The Double-Entry Architecture

Every financial movement must involve exactly two accounts: money leaves one account (Debit) and enters another (Credit). The sum of all accounts in the system must always equal exactly zero.

Transaction 101: Customer Buy ($100)
--------------------------------------
Account                 | Debit | Credit 
User_Stripe_Bal         | $100  |
Merchant_Available_Bal  |       | $97
Platform_Fee_Rev        |       | $3

Tying into Relational Data

A ledger specifically only cares about amounts and timestamps. It should not house business metadata. High-performance teams run the ledger on Postgres with row-level locks to prevent race conditions, referencing the business logic via external UUIDs mapped to `orders_table` or `payments_table`.

Integers Only

Never use floating-point numbers for currency. To avoid precision loss on fractional cents, all ledger databases must store values as integers in the lowest currency denomination (e.g., cents for USD, zero-decimal units for JPY).

A solid ledger makes solving Settlement and Reconciliation infinitely easier by providing a mathematical proof of the system's state at any given millisecond.