Skip to content

Ledger and the Monthly Close

A ledger is an append-only, double-entry record of money movements, and the monthly close is the reconciliation process that proves those records match processor reports and bank activity. Balances are derived from immutable debits and credits, not treated as mutable truth stored in a single column.

Money systems fail when the database stores only the latest balance and treats payments as ordinary state updates. Retries, refunds, processor delays, fees, chargebacks, manual corrections, and partial failures can all make that number wrong while leaving little evidence of why. A ledger exists so every monetary change has an auditable explanation, and the monthly close exists because your database is not the only system describing the same money.

Mechanically, each business event becomes a journal entry containing ledger lines. One account is debited, another is credited, and the entry must balance. The lines are inserted together in a single database transaction, so the system never records only half of a movement. Account balances are calculated by summing relevant lines, or read from a cache that can be rebuilt from the append-only record.

The trade-off is that a correct ledger is more work than a balance column. You need account models, idempotency, transaction boundaries, posting rules, reversal patterns, and reporting queries that understand accounting semantics. Historical mistakes are not edited away, which can feel inconvenient during support or operations work. The honest answer on caching balances is that it depends on volume, latency requirements, and how safely the cache can be regenerated.

Engineers meet this in payment captures, refunds, marketplace payouts, wallet balances, stored value, fees, and revenue recognition. The monthly close compares internal ledger totals with the processor’s settlement and fee reports, then compares those settlements with the bank statement. Mismatches become investigations: missing webhooks, late fees, duplicate attempts, timing differences, or operational adjustments. Corrections are new ledger entries, not mutations of old ones.

Common questions

Is a ledger just a transactions table?
No. A transactions table often records that something happened, but a ledger records the accounting effect of that event. The important properties are balanced debits and credits, append-only history, atomic posting of all lines, and balances derived from entries. A plain table plus a mutable balance column does not provide those guarantees.
Why not update the balance directly for performance?
You can maintain a balance cache, but it should not be the source of truth. Direct balance updates are hard to audit and easy to corrupt under retries or partial failures. The durable truth is the immutable ledger lines. If the cache is wrong, you should be able to discard it and recompute it from the ledger.
What happens when the processor report disagrees with the ledger?
You do not overwrite history to make the numbers match. You identify the cause: timing differences, missing events, processor fees, reversals, failed payouts, or operational mistakes. Then you post new correcting entries where appropriate. The goal of the close is not cosmetic agreement, but an explainable chain from product activity to processor settlement to bank cash.