Scaling a Multi-Vendor Marketplace Catalog
Engineering notes from a multi-vendor marketplace: modelling vendor-scoped inventory, keeping search fast as the catalog grows, and settling payouts without double-counting.
Quick answer
A multi-vendor catalog scales when vendor scoping lives in the data model rather than in query filters, search runs against a denormalised read model updated by events, and money is handled with an append-only ledger. The hardest part is not the product grid — it is inventory correctness and payout reconciliation across independent sellers.
The context
A marketplace with independent sellers, each owning their own products, inventory, orders and payouts. Buyers see one storefront; behind it, every read and write has to be scoped correctly or a vendor sees somebody else's data.
Vendor scope belongs in the model
Adding vendorId to every query is a policy enforced by discipline, and discipline fails at 3am. Scoping was moved into repository constructors: you obtain a vendor-bound repository, and there is no API to query outside that vendor.
const repo = productRepo.forVendor(vendorId);
await repo.list({ status: "active" }); // vendorId cannot be omittedSearch is a different shape of data
The write model is normalised across vendors, products, variants and inventory. The read model for search is one flat document per listing, rebuilt from domain events. Faceted queries stopped touching four collections and browse latency became predictable.
| Concern | Write model | Read model |
|---|---|---|
| Shape | Normalised, per entity | One flat listing document |
| Consistency | Strong | Eventual, seconds |
| Optimised for | Correctness | Facets and sorting |
Inventory is a race condition with a UI
Two buyers, one unit. Reservations with a short TTL at add-to-cart, converted at payment confirmation and released on expiry, removed oversells without locking the catalog.
What I would change next time
- Introduce the event-driven read model on day one rather than after the catalog got slow.
- Make the ledger the first payments artefact, before any payout logic.
- Give vendors an activity log early — most support tickets were 'what happened to my listing'.
Checklist
- Vendor scope enforced structurally, not by convention
- Separate read model for search and browse
- Inventory reservations with TTL instead of optimistic hope
- Append-only ledger for all money movement
- Per-vendor rate limits and abuse controls
- Vendor-visible activity log
Common mistakes
- Filtering by vendorId manually in every query.
- Running faceted search directly against the normalised write model.
- Mutating balances instead of recording ledger entries.
- Letting one vendor's bulk import degrade the whole catalog.
Frequently asked questions
SQL or MongoDB for a marketplace?
Either works. Relational databases make ledgers and constraints easier; document databases make heterogeneous vendor catalogs easier. Decide based on which invariant you are most afraid of breaking.
How do you prevent overselling?
Short-lived reservations created at add-to-cart, converted on payment success and released on expiry, backed by an atomic decrement.
Summary
Structural vendor scoping, an event-driven read model for search, TTL reservations for inventory and an append-only ledger for money — those four decisions carried the marketplace further than any query tuning.
working on something like this?