The problem
Selling the same catalogue on Amazon, Shopify and Walmart means three APIs that disagree about almost everything: how a price is expressed, how stock is reserved, how fast a change propagates, and what counts as an error worth retrying.
When those three drift apart, the shop sells stock it does not have. Overselling costs money twice - once on the refund, once on the marketplace metrics that decide whether you keep selling at all.
How it works
One adapter interface hides the three marketplace APIs behind a single contract, so the business logic never learns which channel it is talking to. Adding a fourth marketplace means writing an adapter, not touching the pricing rules.
Every item moves through a Symfony Workflow state machine: pending, syncing, done. A sync that gets stuck is stuck in a state you can query, not silently missing.
Price and stock updates travel on separate RabbitMQ queues so a slow price recalculation cannot delay a stock correction. Both queues have retry logic and a dead-letter queue behind them, and everything that lands in dead-letter is replayable.
What it bought
Overselling stopped. Sync latency settled under five minutes across more than ten thousand SKUs, and every failed update ended up somewhere a human could see it instead of vanishing into a log.