Inventory sync is the single most critical data flow in a WooCommerce-ERP integration. Get it wrong, and you oversell products, disappoint customers, and erode trust. Get it right, and your store reflects reality — always.
The Problem with Batch Syncing
Many WooCommerce stores start with a cron-based approach: every 15 minutes, pull inventory from the ERP and update WooCommerce. This works until it doesn’t.
Consider: your ERP receives a shipment of 50 units at 10:01 AM. Your sync runs at 10:00 and 10:15. For 14 minutes, your website shows “Out of Stock” while your warehouse has 50 units on the shelf. That’s lost revenue.
The inverse is worse: a customer orders the last unit at 10:02, but the sync at 10:15 hasn’t decremented the ERP count yet. Another customer orders the same “last” unit at 10:10. You’ve oversold.
Real-time sync eliminates both scenarios.
Architecture Options
Option 1: Webhook + Queue
ERP (stock change) --> Webhook --> Message Queue --> Sync Worker --> WooCommerce API
WooCommerce (order) --> Webhook --> Message Queue --> Sync Worker --> ERP API
The message queue (RabbitMQ, AWS SQS, or Redis) decouples the webhook receiver from the processing logic. If WooCommerce is temporarily down, the queue holds the updates until it’s back.
Option 2: Change Data Capture (CDC)
For ERPs backed by a relational database, CDC tools (Debezium, AWS DMS) watch the inventory table for changes and push updates to WooCommerce. This catches changes regardless of how they were made — API, manual entry, or batch import.
Option 3: Polling with Delta Detection
If your ERP doesn’t support webhooks or CDC, poll at short intervals (every 60 seconds) but only process records that changed since the last poll. Most ERPs have a modified_at timestamp on inventory records.
// Delta polling pattern
async function syncInventory() {
const lastSync = await getLastSyncTimestamp();
const changes = await erp.getInventoryChanges({ since: lastSync });
for (const item of changes) {
await woocommerce.updateProduct(item.sku, {
stock_quantity: item.quantity,
stock_status: item.quantity > 0 ? 'instock' : 'outofstock'
});
}
await setLastSyncTimestamp(new Date());
}
Conflict Resolution
What happens when WooCommerce and the ERP disagree on stock levels?
Rule 1: The ERP is the source of truth for absolute stock levels. The ERP knows what’s physically in the warehouse. WooCommerce knows what’s been ordered online. The ERP wins.
Rule 2: WooCommerce decrements are events, not states. When a WooCommerce order is placed, send a “decrement by X” message to the ERP — not “set stock to Y.” This prevents race conditions.
Rule 3: Never let the sync overwrite a pending order. If a WooCommerce order is in “processing” state and hasn’t been sent to the ERP yet, the ERP’s stock count doesn’t account for it. Your sync must subtract pending orders from the ERP count.
Display Stock = ERP Stock - Pending WooCommerce Orders Not Yet in ERP
Handling Product Variants
WooCommerce variations and ERP SKUs often have different structures. A WooCommerce variable product “T-Shirt” has variations (Small/Red, Medium/Blue, etc.), each with its own stock. Your ERP might store these as flat SKUs.
Mapping table:
| WooCommerce | ERP |
|---|---|
| Product ID: 1234 (parent) | — |
| Variation ID: 1235 (S/Red) | SKU: TSH-S-RED |
| Variation ID: 1236 (M/Blue) | SKU: TSH-M-BLU |
Maintain a SKU mapping table in your integration layer. Never rely on matching product names — they change. SKUs are your stable identifier.
Error Handling
Inventory sync failures are business-critical. Build these safeguards:
- Dead letter queue: Failed sync messages go to a separate queue for manual review
- Alerting: Slack/email notification when sync fails or when stock discrepancy exceeds a threshold
- Retry with exponential backoff: 1s, 2s, 4s, 8s, then dead letter
- Circuit breaker: If the ERP is down, stop hammering it. Queue updates and process when it recovers
- Audit log: Every stock change — source, old value, new value, timestamp
WooCommerce API Considerations
WooCommerce’s REST API has rate limits and performance characteristics to consider:
- Batch endpoint:
POST /wp-json/wc/v3/products/batchupdates up to 100 products per request - Variation updates require the parent product ID in the URL
- Stock status must be updated alongside
stock_quantity— they’re independent fields - Webhook reliability: WooCommerce webhooks can fail silently if your server doesn’t respond with 200 within 5 seconds
Monitoring Your Sync
Track these metrics:
| Metric | Target | Alert Threshold |
|---|---|---|
| Sync latency | < 30 seconds | > 2 minutes |
| Failed syncs / hour | 0 | > 5 |
| Stock discrepancy | 0 items | > 10 items |
| Queue depth | < 100 | > 1,000 |
Conclusion
Real-time inventory sync isn’t optional for serious WooCommerce stores. The architecture you choose depends on your ERP’s capabilities, but the principles are universal: treat the ERP as the source of truth, handle decrements as events, build robust error handling, and monitor everything. Start with webhook-driven sync if your ERP supports it; fall back to high-frequency polling with delta detection if it doesn’t.
Last modified: April 3, 2026
United States / English
Slovensko / Slovenčina
Canada / Français
Türkiye / Türkçe