Integrating a Modern ERP With Legacy Systems That Were Never Built to Talk to Each Other
written by Cooter:Labs
published on July 31, 2026
Introduction
Most ERP rollouts don't fail because the new system is bad. They fail, or stall for years, at the boundary where the ERP has to exchange data with something old that was never designed to be integrated with anything — a mainframe accounting system from the 1990s, an AS/400 running the warehouse, a shop-floor control system a vendor stopped supporting a decade ago. These systems usually work fine at the one job they were built for. What they don't have is an API, a webhook, or in some cases even a documented data schema. Getting a modern ERP to talk to them isn't a configuration problem — it's a systems-integration problem with its own failure modes, and treating it like a standard API integration is where most of these projects go wrong.
"Legacy" gets used as shorthand for "bad," but the more accurate description is usually "closed." A COBOL system running on a mainframe, or an AS/400 that's been in production for twenty years, is often stable and well-understood by the handful of people who maintain it — it just wasn't built with the assumption that anything else would need real-time access to its data. That closedness is the actual integration problem: no REST endpoint to call, no event stream to subscribe to, sometimes nothing more than a nightly flat-file export or read access to the underlying database tables. The integration work is building a bridge to a system that was never designed to have one.

Before picking an integration pattern, audit what interfaces genuinely exist: a documented API (rare), ODBC or JDBC read access to underlying tables (more common, and riskier than it sounds — schemas on old systems are often undocumented and full of fields nobody remembers the purpose of), scheduled flat-file exports in a fixed-width or delimited format, EDI transactions if it's a supply-chain system, or in the worst case a terminal screen that has to be scripted against. This changes the entire design. A system that can only produce a nightly export forces batch synchronization whether or not the business wants real-time inventory or order data in the ERP. Committing to an integration architecture before confirming what the legacy side can actually deliver is the single most common planning mistake in these projects.
Batch synchronization — nightly or hourly file transfers, processed and reconciled on a schedule — is simpler to build and easier to debug, and it's the only option when the legacy system genuinely can't produce real-time events. But it means the ERP is always working with data that's hours old, which matters a lot for inventory-sensitive processes and much less for something like historical financial reconciliation. Event-driven integration, where a change on the legacy side (a shipment logged, a work order closed) triggers a near-real-time update, is worth the added engineering cost only when the business process actually needs the freshness — it usually requires wrapping the legacy system in a change-data-capture layer or polling its database for deltas, since the legacy system itself typically can't emit events natively.
The instinct on a lot of these projects is to write a translation script directly from the legacy system's format into the ERP's expected format, and then another one for the next legacy system, and another. That works until there's a third or fourth system in the picture, at which point every schema change on either side means hunting down and updating multiple independent translation scripts with no shared logic. The more durable approach is a canonical intermediate model — a normalized representation of a customer, an order, an inventory item — that every source system maps into and every target system maps out of. It's more upfront design work, but it means a schema change on the legacy side touches one mapping, not every downstream integration that happens to depend on that field.
Legacy integrations fail in specific, recurring ways: a batch file arrives truncated because the export job on the mainframe timed out, a record gets synced twice because a retry fired after a timeout that was actually a slow success, or a field that used to always be populated starts arriving blank after someone changes a process on the legacy side without telling anyone. The integration layer needs to be idempotent — reprocessing the same file or event twice should never create duplicate records — and it needs monitoring that flags anomalies (a batch file with 40% fewer rows than yesterday's) rather than silently ingesting whatever arrives. Building this in from the first version is much cheaper than retrofitting it after the third data-quality incident.
Where an agentic layer is genuinely useful in this kind of integration is the fuzzy-matching problem that shows up constantly: the same customer exists in the legacy system and the ERP under slightly different names, a product SKU was renumbered at some point and both the old and new codes still show up in historical records, or a mapping rule has a dozen documented exceptions that keep growing. An agent that can propose likely matches with a confidence score, and route anything below a threshold to a person instead of guessing, reduces the manual reconciliation queue without pretending the underlying data problem doesn't exist. It's a tool for the matching step specifically — it doesn't replace the work of deciding batch versus event-driven, or building the canonical model, or handling partial failure.
Looking Ahead: Challenges and Innovations
There's often no test environment for the legacy side
Modern systems assume a staging environment that mirrors production closely enough to test against safely. A lot of legacy systems don't have one — the production instance is the only instance, because standing up a second one was never budgeted or the licensing doesn't allow it. That forces integration testing to happen against carefully chosen read-only queries or a manually exported sample dataset, and it means the first real test of the write path often happens closer to production than anyone would prefer. Building in a dry-run mode that logs what the integration would have written, without actually writing it, is usually the practical substitute for a real staging environment.
Institutional knowledge about the legacy system is thinner than anyone admits
The person who understood why a particular field in the legacy schema behaves the way it does, or why a batch job runs in a specific order, has frequently moved on, retired, or simply forgotten the reasoning over the years the system has been running unattended. What's left is behavior that has to be reverse-engineered from the data itself — noticing that a field is sometimes null and sometimes zero and those mean different things, without any documentation saying so. Budgeting real time for this kind of archaeology, rather than assuming the legacy system's behavior is fully knowable up front, avoids a lot of integration bugs that only surface weeks after go-live.
Master data drift accumulates the longer the systems run in parallel
Once the ERP and the legacy system are both live and being updated, even briefly, records drift apart — a customer address updated in one system doesn't propagate to the other, or a status field gets manually corrected in the legacy system outside the normal integration path. The longer both systems stay operational side by side, the more this compounds, and the harder it becomes to trust either one as a source of truth for a given field. Defining, explicitly and in writing, which system owns which fields during the transition period — and enforcing that rather than letting whichever system was updated most recently win — is what keeps this from becoming an unresolvable reconciliation problem later.
The metaverse
The direction most of these integrations are heading isn't more sophisticated middleware — it's fewer integrations to maintain at all, as organizations gradually retire the legacy systems the ERP was originally built to coexist with. But that migration is usually a multi-year process, and until it's complete, the practical trend is toward integration layers that are more observable and more self-correcting: continuous reconciliation that flags drift as it happens instead of surfacing it at quarter-end, and mapping logic that can absorb small schema changes without a manual patch every time. The legacy system doesn't get smarter. The layer standing between it and the ERP has to.
Conclusion
Integrating a modern ERP with a legacy system is a systems-integration problem wearing an ERP-rollout costume. The legacy side dictates the realistic architecture — what it can actually expose determines whether batch or event-driven synchronization is even on the table — and the durable design decisions are a canonical mapping layer instead of point-to-point scripts, idempotent processing that survives partial failures, and an honest read on how thin the institutional knowledge of the old system really is. AI has a real, narrow role in the fuzzy-matching problem that shows up at the seams between systems, but it doesn't substitute for getting the integration architecture right. Get that wrong and no amount of matching intelligence downstream fixes it.
Share this post:
Curious what this means for your business?
Get a personalized ROI estimate, or book a free discovery workshop with our team.