Reclaim
A revenue-recovery engine that prices every move on a failed payment, including the decision to do nothing, and recovers 1.42× what blind retries do.

FBN.2026.01
Reclaim
Design, modelling and engineering
TypeScript, Next.js, PostgreSQL, PGlite, 2026
1.42×
net recovery versus retrying every payment
3,042
held-out events in the evaluation
0.69
ROC-AUC of the calibrated recovery model
574
automated tests, on two operating systems
The problem
Most payment systems ask whether a charge will fail. The harder question arrives afterwards: once the money has slipped away, is it worth spending more money, an agent's time and a customer's goodwill to win it back? Retry loops never ask. They hammer every failure identically, and on real fee structures that costs more than it recovers.
The approach
Reclaim treats recovery as constrained optimisation. For every failed payment, abandoned checkout or overdue receivable, each possible action is scored by expected value: a calibrated logistic regression supplies the probability of recovery, then intervention cost, compute, risk and contact fatigue are subtracted, and doing nothing is priced like everything else. Plain, property-tested TypeScript owns the money arithmetic, idempotency and audit trail. The language model writes message copy and nothing more, barred five independent ways from ever reaching a payments client. Webhooks are acknowledged in milliseconds and settled asynchronously through a Postgres queue with lease-based recovery.
The outcome
On 3,042 held-out events the model never saw, Reclaim recovers 1.42× the net value of retrying everything, at a ROC-AUC of 0.69, guarded by 574 automated tests that run on Linux and Windows against two database drivers. The headline once read a flattering 3×; tracing that number to its source and replacing it with the honest one is part of the work.
What it does
5 capabilitiesEvery move has a price
Each candidate action carries an expected value, and doing nothing is a real, priced option rather than a failure to act.
One engine, three ledgers
Failed payments, checkout abandonment and overdue receivables share one decide(), one risk gate and one audit trail. The second and third arrived as configuration, not new code.
A budget for human attention
Left unconstrained, the policy escalates 91.6% of events. A capped daily budget, ranked by expected value, matches or beats escalating everyone.
A firewall around the model
Mapped types, a dependency-free interface, an ESLint boundary and an import-graph test keep the language model structurally unable to touch money.
Idempotent under fire
A real kill -9 mid-batch, a restart and a lease expiry later, the ledger still settles to exactly one audit row: never zero, never two.
The strata
How it standsIngress
HMAC-verified Razorpay webhooks, acknowledged at a p50 of 36 ms inside a single transaction
Queue
Durable Postgres queue with FOR UPDATE SKIP LOCKED and lease-based reclaim
Decision
Risk gate, then per-action expected value, then argmax: a pure function
Model
Calibrated logistic regression for P(recover | state, action), trained offline
Language
Groq-written copy with a deterministic template fallback, firewalled from payments
Operations
Operator queue, audit timeline, policy simulator, CI on two database drivers
The judgments
The reasoning, on the recordChose
Logistic regression
over gradient boosting
Measured, not assumed. On the identical held-out split it wins on Brier skill (0.162 against 0.135) and ROC-AUC (0.690 against 0.636), and its probabilities stay calibrated, which is what an expected-value engine actually spends.
Chose
A UNIQUE constraint as the idempotency authority
over a distributed lock in a second datastore
One transaction inserts the event and enqueues it. There is nothing to drift out of sync, and duplicate deliveries collapse at the database itself.
Chose
A capped, value-ranked escalation budget
over escalating every doubtful case
No operations team staffs 91.6% of events. Ranking by expected value spends scarce human attention where it recovers the most.
Chose
The honest 1.42×
over the original 3×
The first comparison could not have come out the other way. Asking whether a result could lose is the question that caught it.
A relic from the source
The formulaEV(a) = P(recover | s, a) x RecoverableAmount
- InterventionCost(a)
- ComputeCost(a)
- RiskPenalty(s, a)
- ContactFatigueCost(s, a)
choose a* = argmax EV(a)The cabinet
Captured from the live build
Reclaim, plate I
Screen capture, 2560 × 1600
reclaim-lac-six.vercel.app, MMXXVI
Next exhibit — II
PromptForge