Guide chapters
Payouts
The problem#
A payout looks like a transfer and is actually an answer to the question of how much a seller is owed at a particular moment. That answer depends on orders, refunds, commission, any deductions, and on how much has already been paid.
On top of that comes an asymmetry of time: money leaves once and irrevocably, and a refund can arrive a week later.
Minimum version#
- The amount owed is computed from orders rather than kept as a balance somebody has to keep updating.
- An eligibility rule: which orders enter a payout at all.
- A payout as an immutable record: amount, moment, the orders covered, the transfer identifier.
- Execution by hand, triggered by a person.
The hold window as a parameter#
Almost every marketplace holds a payout for some time after delivery, so that a refund has a chance to arrive. The length of that window follows from the returns policy, not from the architecture.
It should be a configuration value rather than a number typed into the code. The first client with a different returns policy or a different product category will change it in the first week.
| Eligibility condition | Where it comes from |
|---|---|
| Enough time has passed since delivery | the returns policy, a configurable value |
| No open return request | order state |
| The order is not fully refunded | refunded amounts |
| The seller can receive funds | status at the payment provider |
| The order has not been settled already | payout history |
What not to build yet#
- Instant payouts.
- A seller balance as a record updated on every operation. Computing on demand is simpler and cannot drift.
- An automatic schedule, before doing it by hand starts to hurt.
- Negative balance handling, until the first case occurs.
Plan ahead#
A payout is immutable#
A payout record must not be updated when a refund arrives. A refund after a payout is a separate event that reverses part of the earlier one. Overwriting the amount destroys the only trace of what actually left the account.
Eligibility as a rule, not a flag#
An order ready for payout is the result of several conditions checked at payout time. A flag set earlier will drift when a refund arrives after it was set.
The way back from day one#
A refund after a completed payout will happen. The model has to know which payout covered which order, so the right amount can be reversed. Without that link the only option is deducting from future payouts, which ends in a loss with a seller who has stopped selling.
Triggers#
- the first refund after a completed payout;
- a seller asks which orders a given amount covered;
- payouts start taking a fixed block of time each week;
- the first mistake in an amount paid by hand;
- the first discrepancy between the sum of payouts and the statement.
Next stage#
After the second trigger: a statement showing which orders went into which payout. It is the question sellers ask most and the cheapest thing to build. After the third and fourth: a schedule with protection against double execution. After the fifth: reconciliation against provider data.
Common mistakes#
| Assumption | Why it costs |
|---|---|
| "A seller balance is a field." | It drifts on every operation you did not anticipate. |
| "We will update the payout after a refund." | The trace of what actually left the account disappears. |
| "We will deduct the refund from the next payout." | A seller who has stopped selling has no next one. |
| "Eligibility can be a flag." | A refund after the flag was set does not undo eligibility. |
| "The hold window is a constant in the code." | The first client with a different returns policy forces a code change. |
What works in practice#
What mattered most on payouts was tying each one to specific orders. It looks like an accounting detail and is the precondition for two things at once: answering the seller question about what they were paid for, and being able to reverse the right amount when a refund arrives after the transfer.
The second thing: a payout that executes once. Money operations have to be guarded so that a retry after a network error does not send the transfer a second time. This is the kind of problem that costs real money the first time it happens, not just time.
Checklist#
- The amount owed is computed rather than stored as a balance.
- The hold window is a configurable value.
- A payout is an immutable record tied to specific orders.
- There is a way back for a refund that arrives after a payout.
- A retry cannot send the transfer twice.
- A refund at one seller does not touch another seller payout.
I design multi-vendor platforms with onboarding, payments, moderation, and operational workflows.
Explore marketplace development