DEV Community

Cover image for One Payment, Three Ledgers: Where Reconciliation Actually Breaks
Dmytro Nasyrov
Dmytro Nasyrov

Posted on

One Payment, Three Ledgers: Where Reconciliation Actually Breaks

A processor says a payment settled. Your product ledger shows the customer balance and fee entries. The bank account still has no matching credit. None of those records is necessarily wrong, yet the payment is not reconciled.

The mistake is asking which system has the true status. Each system owns a different fact. Reconciliation belongs to the process that can compare those facts, preserve the mismatch and prove what happened at every boundary. A useful design sets invariants across the product ledger, the processor settlement record and the bank statement.

One payment creates three different facts

Your product ledger records the economic event the application accepted: a capture, refund, fee, reserve movement, chargeback or correction. It should preserve the customer-facing and accounting consequences even when an external provider changes later.

A processor owns another view. Its settlement data determines which transactions and adjustments entered a payout. Stripe, for instance, exposes immutable balance transactions and lets automatic payouts retain their association with the transactions they contain. Adyen's settlement details report includes settled payments, fees, corrections, payouts and a payout reference that can appear on the bank statement.

Only the bank statement proves the cash movement. It cannot explain the composition of a processor batch, and the processor cannot prove that a credit reached the bank merely by marking a payment as settled.

This separation is part of payment systems engineering because the integration call that moves money and the evidence that closes the books have different owners. Treating a provider response as all three facts makes the happy path simple and every exception ambiguous.

I use "ledger" here as shorthand for a durable reconciliation surface. A processor report or bank statement may not be a double-entry ledger. The design still needs to preserve their facts as immutable evidence rather than flattening them into one mutable payment status.

The invariant map

Start with a currency and a reconciliation window. Then define the equations that must hold after accounting for cutoffs, fees, reserves, refunds, chargebacks, corrections and foreign-exchange effects.

Boundary Invariant Evidence that closes it What a mismatch means
Product ledger to processor Expected provider payable from internal entries equals the processor's net settlement components internal journal entries plus transaction-level processor report missing event, duplicate event, amount mapping error, fee rule drift, or timing classification error
Processor batch to bank Processor payout amount and currency equal the bank credit after declared bank or FX adjustments payout record, batch reference, value date, and bank statement line payout still in transit, wrong destination, bank fee, FX difference, rejection, or missing cash movement
Period continuity Opening unsettled balance plus new net activity minus payouts equals closing unsettled balance consecutive settlement periods and retained adjustments orphaned balance, late event, duplicated payout application, or a broken cutoff rule
Reference completeness Every bank credit maps to one processor payout and every completed payout maps to one bank credit stable payout reference and a controlled fallback match unlinked cash, one-to-many aggregation, reused reference, or incomplete ingestion

The point is not to force all systems to agree at every moment. They operate on different clocks. The point is to know which differences are expected, which deadline makes them actionable, and what evidence will eventually close them.

A modeled break: settled, posted, but not received

Assume the processor marks a card payment as settled. The product ledger has already posted the customer balance and expected fee. The safeguarding or operating bank account has no corresponding credit.

Do not reverse the customer entry just because the bank credit is absent. "Payment settled" and "payout reached the bank" describe different boundaries. First ask whether the payment was included in a closed settlement batch. If it was not, the first invariant may still be open because of the provider's cutoff, reserve policy or status mapping. If it was included, locate the payout reference and compare the batch net amount with the expected bank credit.

The absence becomes a bank-boundary exception only after the payout has a provider-side completion fact and the agreed arrival window has expired. Until then, the discrepancy needs a state such as awaiting_bank_evidence, not a generic failed flag.

That distinction changes the recovery action. A ledger mapping defect can require a replay from immutable source events. A missing bank credit needs provider or bank investigation. Re-running the original payment cannot repair either one and may create a second economic event.

Build a discrepancy record, not an alert string

A reconciliation job should emit a durable object that another worker or analyst can resolve without reconstructing the original comparison from logs.

{
  "discrepancy_id": "rec_01J...",
  "invariant": "processor_payout_equals_bank_credit",
  "currency": "EUR",
  "window": "2026-08-20",
  "internal_evidence": ["journal_batch_..."],
  "processor_evidence": ["payout_...", "settlement_batch_..."],
  "bank_evidence": [],
  "status": "awaiting_bank_evidence",
  "owner": "treasury_operations",
  "next_check_at": "..."
}
Enter fullscreen mode Exit fullscreen mode

The record names the failed invariant, the evidence already present, the evidence still missing, the current owner and the next permitted action. Its identity should remain stable across retries. Otherwise every polling cycle creates a new exception and hides the age of the original break.

This is where reconciliation design for payment platforms becomes an architectural concern rather than a reporting feature: the discrepancy must survive provider outages, late files, replayed webhooks and human investigation without losing its lineage.

Detect the break at the boundary that owns it

One reconciliation worker can coordinate the process, but it should not become an unquestioned source of truth. Authority remains fact-specific.

Invariant Required evidence Owner Detection time Recovery action
Internal entries equal processor components immutable internal journal and transaction-level settlement rows payments accounting after the processor report closes for the window replay ingestion, repair mapping, or open a controlled accounting adjustment
Processor payout equals bank credit payout ID, batch reference, expected arrival window, and statement line treasury operations when the arrival window expires query payout status, trace the transfer, then escalate to provider or bank
Opening plus activity minus payouts equals closing consecutive balances and every intervening adjustment financial control at period close freeze close, locate orphaned movement, and post only an approved correction
Every external line has one controlled match provider and bank references plus fallback match rationale reconciliation service during ingestion and rematching quarantine ambiguity for review instead of choosing the nearest amount

The detection time matters as much as the equation. Flagging a payout before its contractual arrival window produces noise. Waiting until month-end to detect a duplicated settlement row turns a local ingestion bug into an accounting close problem.

Matching rules also need an order. Prefer stable provider and bank references. Use amount, currency, value date, merchant account and batch metadata only as controlled secondary evidence. A fuzzy match may propose a candidate, but it should not silently convert ambiguous cash into a reconciled state.

The system of record depends on the question

Teams often try to settle the argument by declaring one database the system of record. That is useful for one class of fact and dangerous when applied to all of them.

For customer obligations and internal accounting, the product ledger can be authoritative. A processor remains authoritative for the composition and status of its settlement batch. Cash received belongs to the bank's evidence. The reconciliation record proves that those sources were compared under a named rule and either matched or produced a controlled exception.

This model also makes observability concrete. The useful metrics are not just payment success rate. Track the age of open discrepancies, unmatched value by currency, breaks by invariant, time to first owner, repeated ingestion events and corrections posted without complete evidence.

When the three-ledger model changes

Some architectures collapse or add boundaries.

If the processor is also the contractual ledger of record, the product may not maintain a separate customer-money ledger. The application still needs evidence that processor balances reconcile with bank cash, but it should not invent a duplicate accounting authority.

Prefunded settlement changes the direction of the cash invariant. You reconcile funding movements and consumption of the prefunded balance rather than waiting for a payout after each sales batch. Split settlements, marketplace subaccounts, reserves and multi-currency conversion can add more than three reconciliation surfaces.

The decision rule stays the same: model one invariant for every boundary where economic meaning, provider settlement or cash possession can diverge. Assign an evidence source, deadline, owner and recovery action before calling the payment reconciled.

Which system in your stack can prove a payment is settled when the processor and bank disagree?

Top comments (0)