← Back

Confidential / NDA

Multi-Seller Marketplace Channel

Client, brand and business rules are white-labelled. Lead backend developer and designer (lead-approved) — Laravel, MySQL.

Overview

The client already ran a marketplace app with its own catalog, accounts and cart. They wanted a second channel where independent sellers open shops and sell their own products, inside the same app, the same cart and the same checkout. I designed the channel end to end (approved by my lead) and wrote most of its core services.

What already existed (team / platform): buyer accounts and addresses, category tree, authentication, admin panel shell, media library, and the original channel's orders. Some later moderation features on shops (suspensions, visibility rules) were added by a colleague.

The Problem
  • Two channels had to share one cart and one checkout, while stock, payment and order flows stayed separate per seller.
  • Stock is limited per variant. Two buyers must never both get the last unit, but idle carts should not lock stock either.
  • Payment confirmation is asynchronous. It can arrive late (after the buyer cancelled), twice, or not at all.
  • One checkout can include orders from several sellers, and each can be cancelled or refunded on its own.
The Solution
  • A seller onboarding and catalog module with up to two variant axes per product and a price and stock row per variant.
  • A cart extended with a channel flag so both channels coexist in one basket.
  • Stock is held when the buyer opens the checkout summary, not when they add to cart, and released when they leave or the hold expires.
  • One checkout session groups child orders, one per seller, under one payment.
  • Cancel, payment confirmation and a background payment check all go through the same locked path, so the order ends in one consistent state whichever arrives first.
  • A per-seller order lifecycle with cancellation, return and refund cases, and seller income credited only after a buffer period.

Features

Engineering highlights

Stock correctness under concurrency: row locks on the variant before checking availability; a separate held counter, so on-hand stock only changes when an order is really paid or returned; a fixed lock order (variant, then hold) everywhere.

Late and duplicate payment events: cancel asks the payment provider first and does not cancel if the provider is unreachable; a late confirmation revives a cancelled checkout instead of losing a paid order; a duplicate confirmation does nothing; a background check recovers payments whose confirmation never arrived.

Idempotent refunds: every refund and restore step checks whether it already ran, so retries and double clicks are safe. A shared payment is marked partially refunded while other orders in the same checkout are still paid.

Explicit state machines for shops, holds, orders, refunds and return cases, with a status history per order.

Scheduled jobs that cannot overlap, and seller income credited once with a timestamp guard.

Result

The full flow from seller onboarding to checkout, fulfilment and refunds went live. I handed it over after delivery and the team continues to run and extend it.

Diagrams

Loading diagrams…

Technical notes