Marketplaces where the money sits in the middle
A marketplace with two sides, a payment held between them, and an AI studio that bills by the generation. The hard part is never the catalogue — it is deciding, in code, the exact moment money and files change hands.
The problem
Two-sided marketplaces look like a catalogue with a checkout bolted on. They are not. The catalogue is a week of work. What takes the other months is the question every such product has to answer: who is holding the money right now, and what has to be true before it moves. Get that wrong and you do not get a bug report. You get a buyer who paid and received nothing, or a seller who delivered and was not paid — and either one costs you the marketplace, because the whole product is a promise that neither can happen.
What is hard about it
The order is a state machine, and money is one of the states
An order moves through pending, awaiting payment, in progress, review, and then done, revision or dispute. Each edge has a rule about funds and file access, and every edge needs a negative case: what happens if the buyer pays twice, if the seller vanishes at review, if either account is banned mid-deal. We wrote a dedicated test suite for that last one, because a ban that quietly strands a paid order is worse than no ban at all.
The payment provider is the source of truth, not the phone
The buyer pays in a provider web view and the app may be backgrounded, killed or offline before the payment finishes. So the order does not start when the screen says success — it starts when the provider posts a webhook to the backend. That means treating repeats and out-of-order deliveries as normal traffic rather than as errors, and it means the client is never allowed to assert that money arrived.
Delivered work has to be worthless until it is paid for
The seller uploads a video and the server transcodes a watermarked copy with FFmpeg. The buyer reviews only that copy. The clean original is released at the moment the work is accepted, and the watermarked version stays in the order archive as evidence if a dispute is opened later. File access is therefore not a permission on a user — it is a function of the order state.
An AI studio where every click spends real money
Generation is metered in credits: packages are bought, generations are charged, and a failure refunds. The balance is debited inside one database transaction with the balance condition in the update itself, so two taps cannot spend the same credit twice, and every movement is written to a ledger rather than adjusting a number in place. Generation runs asynchronously through queued, processing and then done or failed; on failure the credits go back with their own refund entry, because charging for something that did not happen is the fastest way to lose a paying user.
The AI provider is behind an interface on purpose
Image, video and video-compilation generation sit behind one provider interface, injected by token, with a mock alongside the real Vertex AI implementation. That is not architectural neatness — it is what lets the whole credit and refund economy be tested end to end on every commit without spending a rouble on inference. There is also a free discussion mode with an admin-editable system prompt, so the paid path is the one that produces media, not the one that answers questions.
Most of the work is the paths nobody demos
The build ended with 173 end-to-end tests across 24 suites, and their names are the honest map of where the difficulty was: deposits and their card fallback, the deposit cron, wallets, order submission and status, watermarking, ban effects, chat limits, and three separate suites of nothing but negative cases. The happy path was never the risk.