Escrow with reversal¶
Background concept — holding accounts that must net to zero, even when a transfer fails.
What it is¶
An escrow (or "suspense") account is a temporary holding spot for an in-flight transfer. A multi-step transfer moves money into escrow from the originator, then out of escrow to the recipient. If the recipient-side leg fails — bad account, compliance hold, NSF — the transfer reverses: the money moves back from escrow to the originator.
A complete transfer cycle has three possible shapes:
- Success: originator → escrow → recipient. Escrow nets to zero.
- Failure + reversal: originator → escrow → back to originator. Escrow nets to zero.
- Stuck: originator → escrow, then nothing. Escrow is non-zero and the money is in limbo.
The healthy state: escrow account balance = zero every EOD.
The problem it solves¶
Escrow lets a transfer be posted atomically from the originator's perspective ("my money is gone") while the recipient side clears asynchronously. This is essential when the recipient-side leg involves external validation (compliance, account-status check, funds availability).
The failure mode to watch for: the recipient leg fails silently, or the reversal doesn't post. The originator's money is "in escrow" indefinitely, but no one tells them, and the escrow account slowly accumulates stuck balances.
How L1 surfaces this¶
Two L1 invariants catch the two failure shapes:
- Stuck Pending (rail-level
max_pending_agewatch) — a transfer entered escrow but neither settled nor reversed in time. - Stuck Unbundled (rail-level
max_unbundled_agewatch) — a Posted leg sits without its parent transfer's other legs landing.
Plus the universal Drift + Expected EOD Balance checks: any
escrow / suspense account with expected_eod_balance: 0 declared in
the L2 instance will surface as a violation when EOD ≠ 0.
See L1 Reconciliation Dashboard for the visual surface.