In financial software engineering, storing account balances as a mutable integer in a database table is a common anti-pattern. If a user receives concurrent payout transfers or executes multiple transactions simultaneously, database updates can experience race conditions, lockups, and ledger sliding.
A double-entry system treats balances as dynamic aggregations of an immutable list of journals. Rather than updating a balance column directly, we create credit and debit rows inside a journal table.
CREATE TABLE ledger_entries (
id UUID PRIMARY KEY,
account_id UUID NOT NULL,
entry_type VARCHAR(10) NOT NULL, -- 'CREDIT' or 'DEBIT'
amount NUMERIC(18, 4) NOT NULL,
correlation_id UUID NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_ledger_account_time
ON ledger_entries (account_id, created_at DESC);| Parameter | Mutable Balance (Anti-pattern) | Journal Ledger (Double-Entry) |
|---|---|---|
| Write Speed | Slow (locks table rows during balance queries) | Fast (append-only write insertions) |
| Audit Posture | Weak (no historical verification of slide events) | Absolute (reconstruct values by summing logs) |
Our engineers can audit your current codebase, design database schemas, and map migration routes.