June 11, 2026, Luboš Zápotočný
Why your ERP and your e-shop disagree about stock
The synchronization failure every store eventually encounters: two systems that both believe they own the stock number, and the patterns that resolve it.
Sooner or later every shop with an ERP encounters the same support ticket: the storefront says five in stock, the warehouse says zero, and a customer has just paid for something that doesn’t exist. The support team treats it as a one-off error, but it traces back to an architecture decision nobody remembers making.
The root cause is ownership
When the numbers diverge, everyone debugs the synchronization script. But the script is usually doing exactly what it was told; the problem is that two systems both believe they own the stock number. The ERP decrements when it books an order. The shop decrements when checkout completes. Both are right by their own rules, and the sync job has no rule for deciding which value prevails.
The fix is one principle: one system of record per fact. Stock truth lives in exactly one place, almost always the ERP or the WMS, because that’s where stock is booked and where goods physically move. The shop holds a cached copy for display and a reservation. Once that’s explicit, every sync question has an answer: when in doubt, the system of record wins.
The recurring failure modes
With ownership settled, the remaining bugs are mechanical, and they repeat across platforms and ERPs:
- Lost updates. The ERP pushes a stock change, the shop is mid- deploy or rate-limits the call, and nobody retries. Weeks later someone asks why one SKU has been “out of stock” all month.
- Duplicate deliveries. The same webhook fires twice (webhook delivery is typically at-least-once, so the same event can arrive more than once), and the handler decrements stock twice.
- Full syncs racing deltas. A nightly full import and event-driven updates run against the same rows; whichever finishes last wins, and it’s sometimes the stale one.
- Mapping drift. A SKU renamed in the ERP silently becomes a new product in the shop; the old one keeps its stale count forever.
- Bundles and kits. The shop sells a set; the ERP counts components. If the set-to-component conversion lives in a spreadsheet, expect it to be out of date.
The patterns that resolve it
The integration layer that stops producing these tickets looks the same regardless of which ERP is behind it:
- Deltas plus reconciliation. Event-driven updates for speed, and a periodic full comparison that finds what the events missed. The reconciliation is what makes the fast path trustworthy.
- Idempotent consumers. Every update carries an identifier the consumer deduplicates on, so processing it twice changes nothing. This one property absorbs retries and replays. Concurrency conflicts are a separate problem: lost updates and full-syncs-racing-deltas need version stamps or sequence numbers so a stale write can’t overwrite a newer one.
- Correlation IDs end to end. When order 18342 never reached the warehouse, “where did it go” should be answerable from the logs in a minute or two.
- Alert on divergence. A sync that reports success while numbers drift apart is worse than one that fails outright. Compare aggregates on a schedule and page someone when the delta grows.
- Reservations with expiry. If your setup reserves stock early, a cart holds it for minutes and an unpaid order for longer; by default, though, reservation happens at order placement, not add-to-cart. Either way, everything expires back to the system of record. Overselling during campaigns usually traces to reservations that never expire or never existed.
None of this depends on the vendor. We’ve built the same architecture against NetSuite, Business Central, Odoo, and the Czech and Slovak systems like Pohoda and Money S5 that international connector vendors tend to ignore. That long tail is a large part of why our integration work exists.
If your shop and your ERP currently disagree about stock, the place to start is making the ownership question explicit. If you want help, contact us. Deciding where each fact lives is system design; once that decision is made, building the sync is straightforward.