Shopify ERP Integration: Patterns That Actually Work
The reliable integration patterns for connecting Shopify to NetSuite, SAP, or Dynamics — order sync, inventory sync, and what to avoid.
- 01The two sync directions
- 02Order sync: the reliable pattern
- 03Inventory sync: avoiding overselling
- 04Error handling and observability
The two sync directions
A Shopify-ERP integration has two primary sync directions: Shopify → ERP (order creation, customer data) and ERP → Shopify (inventory levels, pricing, fulfilment status). Getting these directions right architecturally is the most important decision in the integration design.
Shopify → ERP should be event-driven: Shopify webhooks fire on order creation, and your integration immediately creates the corresponding ERP record. Don't poll Shopify for new orders — webhooks are faster and more efficient.
ERP → Shopify is typically scheduled: inventory levels sync every 15-60 minutes depending on how critical real-time accuracy is. Pricing syncs when prices change in the ERP (triggered by an ERP workflow or checked on a schedule). Real-time inventory sync from ERP to Shopify is possible but adds complexity — usually only worth it for high-velocity SKUs.
Order sync: the reliable pattern
The reliable Shopify → ERP order sync pattern: Shopify fires an `orders/create` webhook → your integration receives it, validates it, and stores it in a queue → a worker picks up the queued order and creates it in the ERP → success/failure is logged and any errors alert the operations team.
The queue is critical. Processing webhooks synchronously (create the ERP order within the webhook handler) means a slow ERP API response causes webhook delivery failures and retries. A queue decouples webhook receipt from ERP processing.
Idempotency: Shopify will retry webhook delivery if it doesn't get a 200 response within 5 seconds. Your integration must handle duplicate webhook deliveries without creating duplicate ERP orders. Use the Shopify order ID as a deduplication key — check if an ERP order with that ID already exists before creating a new one.
Inventory sync: avoiding overselling
ERP → Shopify inventory sync: your integration queries the ERP's inventory API for current stock levels, then uses Shopify's InventoryLevel API to update quantities per location.
The main pitfall: updating inventory one variant at a time is slow for large catalogues. Use Shopify's `inventoryBulkAdjustQuantityAtLocation` mutation for batch updates — you can update up to 250 inventory items per mutation call.
For critical SKUs where overselling is unacceptable: consider near-real-time sync (every 5 minutes) and setting a safety buffer (hold back 2-3 units from what the ERP reports to Shopify). For less critical SKUs, hourly or 4-hourly syncs are usually sufficient.
Error handling and observability
Integration failures are inevitable — ERPs have maintenance windows, APIs have rate limits, and network calls fail. Your integration needs to handle these gracefully rather than silently losing data.
Minimum observability requirements: every sync run should be logged with status (success/partial/failed) and record count. Every error should be captured with the original payload (so you can retry). Repeated failures should trigger an alert (email or Slack) to the operations team.
Sentry works well for error capture. A simple admin dashboard showing the last N sync runs with status, timestamp, and error count gives the operations team visibility without needing to check logs directly.
For the queue, Redis (with Bull/BullMQ) or a managed queue service (SQS, CloudTasks) both work. The key requirement: failed jobs should be retried with exponential backoff, and eventually move to a dead-letter queue for manual review rather than being silently dropped.
Need help implementing this?
I build what I write about. If you need this implemented on your Shopify store, get in touch.
Discuss your projectReady to build this on your store?
Let's scope it.
I reply personally within 24 hours.