ADR-012: Double-Entry Balance Ledger as Immutable Audit Trail¶
- Date: 2026-08-09
- Status: Accepted
- Phase: Phase 3C
Context & Problem Statement¶
Directly mutating users.balance without an explicit ledger record creates financial audit risks: if a balance value becomes corrupted or disputed, there is no immutable audit trail to reconstruct the historical sequence of balance states or verify financial integrity.
Considered Options¶
- Single Balance Field Mutation (
users.balance): Simple, but lacks historical auditability and makes financial balance reconciliation impossible. - Double-Entry Balance Ledger (
balance_ledgertable): Write two immutable ledger entries (DEBITfor sender,CREDITfor receiver) capturingamount,balanceBefore, andbalanceAfterinside the same@Transactionaldatabase boundary as the money transfer.
Decision Outcome¶
Chosen Option: Double-Entry Balance Ledger (balance_ledger table)
Rationale¶
- Financial Auditability: Every money movement creates two immutable ledger entries documenting exact balance state changes before and after execution.
- Reconciliation Support:
users.balanceacts as a high-performance denormalized field; the actual source of financial truth can be reconstructed at any time using aSUM(CASE WHEN entry_type = 'CREDIT' THEN amount ELSE -amount END)SQL aggregate query over thebalance_ledgertable. - ACID Atomicity: Sender debit, receiver credit, transaction record, and both ledger entries execute in a single database transaction.
Consequences¶
- Positive: Complete audit trail, balance reconstruction capability, financial compliance.
- Negative / Trade-offs: Increases database row writes per transaction from 3 to 5 (2 user updates, 1 transaction record, 2 ledger records).