Recovery playbook
Recovery on separate charges and transfers
Destination charges automate the transfer and inherit the famous default leak. Separate charges & transfers automate nothing: the charge lands on your balance, transfers happen when your code says so — possibly later, possibly partially, possibly to several accounts. You gain control over timing and routing and inherit responsibility for every correctness detail the destination model got free. Recovery here uses the same levers as everywhere else; the differences are ordering hazards and the discipline manual rails demand.
The model in one paragraph
Charge lands on the platform balance in full. Your code creates transfers — on fulfilment, on milestone, on schedule — moving funds minus your application fee to connected accounts. Refund liability is unambiguous: the platform’s, immediately and entirely. Escrow-style flows, milestone marketplaces and B2B pay-on-approval models live here.
Three manual levers
Reverse the transfer (proportional math unchanged). Refund the fee standalone (net-margin check unchanged). Net future transfers (terms unchanged). What changes is that nothing fires automatically: the refund call does not hint that a transfer exists, and the transfer creation does not know a refund happened. Every connection between them is code you wrote.
The refund-before-transfer race
Refund lands before the transfer exists — cancellation inside the escrow window, say. Naive checks report zero owed because there is no transfer to reverse; then the transfer goes out at full value and the leak is born retroactively. Expected-reversal computation must therefore also run at transfer creation: look up whether the source charge carries unrefunded-but-refundable state, and net the transfer accordingly.
// At transfer creation for a previously refunded charge:
const expected = Math.round(
(charge.amount_refunded / charge.amount) * intendedTransferAmount,
);
const adjusted = Math.max(0, intendedTransferAmount - expected);What FeeGuard does about it
Detectors run on both refund and transfer events, serialised per charge behind a distributed lock with a short delay, so findings survive either ordering. The per-charge lock is not decorative: two events racing otherwise both read pre-correction state and raise duplicate findings — the false-positive factory that gets monitoring switched off.
Common questions
Is refund liability different in this model?
No — platform either way. What differs is control over transfer timing, which is exactly the lever that makes recovery easier when used deliberately.
Do application fees work here too?
Yes — taken on the charge at creation, subject to the same proportional refund rule and the same net-margin guard against double-counting.