We've inherited more broken ERP integrations than we've built from scratch, and after enough of them, the failure modes start to repeat.
They're built as a one-time export, not a living system
The most common pattern: someone writes a script that exports a CSV from the storefront, or the ERP, on a schedule, and something on the other end imports it. This works fine in the demo. It fails quietly in production the first time the export runs while an order is mid-checkout, or the CSV format changes because someone added a custom field in the ERP, or the cron job silently stops running and nobody notices for two weeks because nothing threw an error — it just stopped updating.
A nightly batch sync means your storefront inventory is, at best, a day old. For any business with real order volume, that's the difference between "quote confidently" and "oversell and apologize."
Nobody agreed on which system owns which data
This sounds basic, but it's the root cause behind most of the integrations we've had to untangle. If both the ERP and the storefront can update inventory counts, and there's no clear rule for which one wins when they disagree, you end up with a race condition baked into your business process. The same problem shows up with pricing, order status, and fulfillment — every field needs one system of record, and the integration's job is to propagate from that source, not to let both sides negotiate.
Retry and idempotency were never considered
APIs fail. Networks time out. Webhooks arrive twice, or out of order, or not at all. An integration built without idempotency keys and retry logic will, eventually, double-create an order or silently drop one — usually discovered when a customer calls asking where their order went, not from a monitoring alert. This is the least visible part of integration work and the part most often skipped under deadline pressure, which is exactly why it's the part that causes the 2am pages later.
It was scoped as a project instead of a relationship
ERPs get upgraded. Custom fields get added or renamed. API versions get deprecated. An integration that isn't monitored, versioned, and maintained the same way any other production system is will eventually break silently when the ERP side changes something nobody told the storefront team about. Point-to-point integrations without observability — no logging of what synced, when, and whether it succeeded — turn "something's wrong with inventory" into a multi-day investigation instead of a five-minute log check.
What doing it right actually looks like
The most complex integration we've built end-to-end was a custom Shopify App connecting a manufacturing client's storefront to ECi Manufacturing's M1 ERP — inventory, orders, quotes, and fulfillment status, flowing bidirectionally, replacing what had been manual reconciliation eating real staff time every week. The reason it holds up in production isn't a clever trick — it's the boring fundamentals: webhooks instead of polling or batch exports, a clear rule for which system owns each field, idempotent processing so a duplicated webhook doesn't duplicate an order, and logging good enough that when something does look off, we can answer "what happened and when" in minutes, not days.
None of that is exotic engineering. It's just the difference between building an integration and building a script that happens to integrate two systems once.