Escrow Fees Engine: One Rule, Computed When the Money Moves
How seller payout, platform fee shares and buyer refund are computed and written on every release, refund or split — from a single platform-wide rule.
An escrow transition that moves money has to do it atomically. If the seller payout writes but the platform fee doesn’t, you have an inconsistency that has to be repaired by hand on a Friday afternoon. The fees engine prevents that by computing every share in one transaction and writing one settlement row per money movement before the escrow is allowed to change status.
One rule for the whole platform
There is exactly one fee configuration, set by ReVend. It has a type — percentage, flat, or hybrid (percentage plus flat) — and a split: buyer pays, seller pays, 50/50, or a custom buyer/seller share. Tenants do not configure fees, not per category, not per outcome, not by volume tier. What a tenant gets is /escrow/fees: a read-only view of the current rule, the buyer and seller shares, a worked example on a sample deal and the date the rule was last changed. A fee screen everyone could edit would be democratic, energetic and financially catastrophic.
When the fee is computed
At release — not when the escrow is created. The reason is the split outcome: when compliance divides a disputed amount, the fee has to be computed on what each party actually receives, not on the original total. Computing early would mean recomputing later, and recomputing money is how reconciliation meetings are born.
The split calculation
For a standard release: the fee is the amount times the percentage, or the flat amount, or both; rounded first, then capped so it can never exceed the escrow amount. The whole fee comes out of the amount the buyer deposited, and the seller’s payout is what is left. The buyer and seller shares are accounting attribution rather than two separate charges: they add up to the same total fee, and they exist so finance can book the revenue per side. The engine writes a seller_payout row, a platform_fee_buyer row and a platform_fee_seller row.
For a refund: the buyer gets the full amount back and no fee is charged at all. One buyer_refund row. This is a deliberate choice — a buyer who was right should not pay for having been right, and a fee on refunds would discourage the disputes that deserve filing. The same rule applies when an outbound is cancelled before anything shipped and the held escrow is refunded automatically.
For a split: the fee is computed only on the part released to the seller, and the part refunded to the buyer carries none of it. The compliance officer sees both numbers before confirming the decision.
Fail-closed
The settlement rows are written first, the status flip second, both in the same database transaction. If the fee configuration is missing, the write raises and the whole transaction rolls back: the escrow stays held (or in dispute), and the next attempt tries again once the configuration exists. A blocked escrow is annoying. A released escrow without a payout row is an incident.
Currency
Amounts carry the currency of the escrow. When a deal crosses currencies, the exchange rate is locked on the escrow itself at acceptance — rate, timestamp and source — using the daily rates refreshed at 07:00, so a dispute six months later reconstructs the exact rate rather than today’s. On the settlements page, payouts in mixed currencies are never summed into one number; finance gets one batch button per currency.