← Blog
7 min read

The mapping your ERP vendor never documented

In an ERP migration the export is easy. The hard part is the undocumented business logic the old system encoded over years, and recovering it before go-live.

Ray Kameda
Ray Kameda
Co-Founder & Chief Product Officer
Two-panel bar chart titled 'Data issues rank among the top causes of ERP project overruns.' Left panel, reasons for budget overruns: Additional technology 51.2%, Staffing underestimated 39.5%, Organizational issues 39.5%, Data issues 34.9% highlighted in orange, Consulting fees 32.6%, Technical issues 27.9%, Scope expanded 25.6%. Right panel, reasons for timeline overruns: Resource constraints 56.1%, Technical issues 51.2%, Data issues 46.3% highlighted in orange, Scope expanded 39.0%, Organizational issues 39.0%, Unrealistic timeline 24.4%, Vendor shortfall 2.4%. Source: Panorama Consulting Group, The 2024 ERP Report.

The reason ERP migrations slip is measurable. In Panorama's 2024 ERP Report, data issues were cited by 34.9% of the projects that ran over budget and 46.3% of those that ran late, a top-four cause of both. Those data issues are rarely the raw rows failing to move. They are the meaning that failed to move with them. What follows is where that meaning hides, why it decides whether the new system reconciles, and how to recover it before go-live.

The export is not the problem

Ask a program owner what worries them about the migration and getting the data out is rarely the first answer. Modern ERPs, even old ones sitting on a SQL Server database, will give you the tables. The worry is what the tables mean. A field called status holds the integer 3, and only the old system, or the person who configured it in 2014, knows that 3 means released to production but not yet invoiced. A custom field added during an implementation five years ago drives a calculation that half the reports depend on. None of this is recorded in documentation. It is embedded in the software's behaviour, and maybe in a few people's heads, if they still work at the company.

Beetl query view running SELECT star FROM old_orders, showing a raw ERP export where order status is stored as bare integers from 1 to 5, order type as single letters A, B and R, and a custom_field_7 column of Y and N flags whose meaning is nowhere in the data. Cryptic raw order status codes.

One manufacturer described this to us while planning their move to a new ERP. Their assessment was blunt: not everything the old vendor modelled is mapped or explained anywhere, so they expected to have to work around it. For a real ERP migration, that is the normal state of affairs.

What "undocumented mapping" actually covers

"Business logic" is vague enough to ignore until it is too late, so it helps to be specific. In practice it is three recurring things:

  • Status and type codes. Every ERP encodes the state of an order, a delivery, or an invoice as a code, and what each code means is a local decision. Moving to a new system means someone has to say which old code maps to which new one, and that is a business judgement rather than a lookup.
  • Custom fields. Almost every real deployment has fields added after go-live to capture something the standard model missed. They often feed calculations or filters that matter, and they are the least documented part of the system precisely because they were added under time pressure.
  • Derived and workflow logic. The old system did not just store data, it applied rules. This order type skips a step, that customer gets a different tax treatment, this document cannot post until another one exists. Some of that logic has to survive the move, and it is invisible in a raw export.

Why it stays undocumented

None of this is negligence. ERP vendors model this behaviour inside their software as a matter of course, and they have little reason to write a plain-language explanation of every customer-specific configuration. The people who made the configuration decisions move on. The knowledge that remains is distributed across the team as habit rather than held anywhere you can read. For a system that has run the business for a decade, the documentation is the running system.

Recovering the logic in a form you can check

The way Beetl approaches this is to treat the old system's data and behaviour as the source of truth, and to reconstruct the mapping from it rather than from a document that does not exist. We read the tables, look at how values actually distribute, and propose a mapping: this old code corresponds to this new one, this custom field feeds this rule.

Beetl pipeline builder for the mapped_orders pipeline: three source datasets, old_orders, status_map and type_map, feed one explicit SQL transformation stage that maps the old status and type codes to new labels, makes the rebate rule explicit, and flags rows that need human review. The stage carries Working and Deployed versions and writes a Gold dataset named mapped_orders. Transform raw data into comprehensible data with mapping logic.

The part that matters is that the proposal is inspectable. We use AI to draft the mapping definition, because reading through years of accumulated configuration is exactly the kind of work LLMs are best for, but the output is a definition a person can read and approve rather than a black box that transforms the data invisibly. Someone who knows the business looks at the proposed mapping, corrects the cases the data alone cannot settle, and signs it off. The integration does not disappear into an opaque agent. It becomes an explicit, versioned artefact that says what the migration will do.

Reconciliation is the test

A recovered mapping is only trustworthy if the numbers hold. For each group of records, the customers, the products, the open orders, the receivables, the totals on the old side and the new side have to tie out, and the exceptions have to be explained rather than rounded away. That reconciliation is how you know the undocumented logic was actually captured and not quietly dropped. A migration that loads without errors but does not reconcile has usually lost exactly the business logic this piece is about.

Beetl reconciliation query grouped by new status while the mapping is still incomplete. An UNMAPPED group sits at the top flagged FAIL, because two rows carried an old status code with no approved mapping. The other groups read OK, with one marked REVIEW. Before: 2 rows carry a status code with no approved mapping, so the group fails loudly instead of loading silently.

The same reconciliation after the missing code is mapped to On hold. Every group now reads OK, except one still marked REVIEW for a return sitting at a production status that a human has to confirm. After: The unmapped code is resolved, and one row stays in review for a person to settle.

Keeping the transformation explicit and the result reconcilable, rather than trusting a step you cannot see into, is how we think about data work in general, not only in a migration.

The takeaway

If you are scoping an ERP migration, put the budget on the mapping rather than the export. The raw data will move. What decides whether the new system tells the truth is whether the undocumented logic came with it, and whether you can check that it did. The data issues that show up in a third of over-budget migrations are rarely the raw rows. They are the logic that moved without its meaning. The most useful thing we can do on a migration is turn that hidden logic into something explicit, reviewable, and reconciled before anyone depends on it.

FAQ

What is undocumented business logic in an ERP migration?
It is the meaning the old system encoded but never wrote down: what each status or type code stands for, what custom fields drive, and which rules run behind the scenes, such as an order type that skips a step or a customer that gets a different tax treatment. The raw export carries the values but none of these rules, and a migration that drops them loads without errors yet stops reconciling.
How do you find logic that isn't documented anywhere?
By reading the data and the old system's behaviour rather than a document. How values distribute, which codes co-occur, and what the reports actually compute all reveal the rules. AI is good at surfacing candidate mappings from that; a person who knows the business confirms them.
Can't AI just do the whole mapping?
It can draft it, and that saves a lot of the reading. It cannot settle the cases where the data alone is ambiguous, which is why the mapping is proposed to a human as an inspectable definition and approved rather than applied silently.
How long does recovering the mapping take?
It depends on how much custom configuration the old system accumulated, which is why the export timeline is a poor guide. The mapping work scales with the business logic, not the row count.
What if the old system has no documentation at all?
That is the common case, and it is workable. The running system is the documentation; the job is to read it back into an explicit mapping before switching it off.

Maintaining something like this by hand?

Talk to us