Three weeks after launching Nventory we had a silent bug.
Inventory was updating correctly everywhere.
Except one seller's WooCommerce store.
Every sync completed successfully.
Every log showed green.
Every API call returned
200.
The seller's stock was quietly wrong for eleven days before anyone noticed.
The bug wasn't in the sync layer.
It was in the verification step we hadn't built yet. javascript // What we were doing async function updateInventory(channel, sku, qty) { const response = await channel.setInventory(sku, qty); if (response.status === 200) { await auditLog.record({ sku, qty, channel: channel.id, status: 'success' }); return true; // assumed success } } // The problem // WooCommerce was returning 200 with a silent validation error // The inventory wasn't updating // The log showed green // Nobody knew for eleven days We were trusting the API response instead of reading back the actual state.
The fix javascript // What we do now async function updateInventory(channel, sku, qty) { const response = await channel.setInventory(sku, qty); if (response.status !== 200) { throw new ChannelAPIError(channel.id, response); } // Read back — verify the write actually took effect const verification = await channel.getInventory(sku); if (verification.qty !== qty) { // The API said success.
The state disagrees. await deadLetterQueue.push({ channel: channel.id, sku, expectedQty: qty, actualQty: verification.qty, retryAt: Date.now() + backoffMs(0) }); } await auditLog.record({ sku, qty, channel: channel.id, status: 'verified', // not just 'success' verifiedAt: Date.now() }); return true; } One word change in the audit log — from success to verified — that represents an entirely different level of confidence in the data.
Why this happens more than you think Most channel APIs have at least one scenario where they return a success response without actually completing the operation.
WooCommerce returns 200 when a product update hits a validation constraint it doesn't surface in the response body.
Amazon SP-API returns success for inventory updates that are silently queued rather than immediately applied. eBay returns Ack: Success with errors buried in a separate Errors array that most implementations never check. javascript // eBay — the classic trap const response = await ebayAPI.reviseInventoryStatus(params); // Naive check if (response.Ack === 'Success') return true; // WRONG // Correct check if (response.Errors && response.Errors.length > 0) { throw new EbayAPIError(response.Errors); } // Then verify const verification = await ebayAPI.getItem(itemId); if (verification.Quantity !== expectedQty) { throw new InventoryMismatchError(); } The broader principle Every external write in a distributed system should be followed by a read that confirms the state changed correctly.
This is especially true for inventory data where the cost of silent failure is immediate and measurable — a seller shows stock that doesn't exist, an oversell happens, a customer gets a cancellation email. javascript // The pattern we now apply to every channel integration class VerifiedInventoryUpdate { async execute(channel, sku, qty, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { try { // Write await channel.setInventory(sku, qty); } backoffMs(attempt) { return Math.min(1000 * Math.pow(2, attempt), 30000); } } What changed after this bug Three specific things: Every write has a read-back.
Not just for WooCommerce.
Every channel.
Every time.
The extra API call is worth it.
Audit logs say "verified" not "success." The distinction matters.
Success means the API returned
200.
Verified means the state actually changed.
We only log verified now.
Silent failures go to DLQ immediately.
A mismatch between expected and actual state isn't an error to retry inline — it's a failure to investigate.
It goes to the dead letter queue with full context so it can be resolved without data loss.
This is the architecture we've built into every one of the 40+ channel integrations at Nventory — because when you're syncing inventory across Amazon, Shopify, WooCommerce, Flipkart, and eBay simultaneously, a single silent failure can corrupt stock counts across every connected channel before anyone notices.
The eleven days taught us one thing above everything else: Green logs are not the same as correct data.
Build verification into every write.
Assume every API will silently fail you at least once.
Because it will and you won't know until eleven days later when a seller asks why their stock is wrong.
Trust nothing.
Verify everything.
We're building Nventory — multichanial inventory and order management, free forever.
Also available on the Shopify App Store if you're building for multichannel sellers.
Questions welcome in the comments — happy to go deeper on any of the verification patterns.