A record that loads successfully is not the same as a record that works. In enterprise systems, data has structure — and if you migrate the data without respecting that structure, you get a target system full of records that reference things that do not exist.
A purchase order cannot exist without a supplier. A goods receipt cannot exist without a purchase order. An invoice cannot exist without a goods receipt. This is not a project management opinion. It is a structural fact about how enterprise systems work.
Every enterprise system enforces dependencies between object types. These dependencies are not optional. They are hard constraints. If you attempt to create a purchase order that references a supplier that does not exist in the target system, the creation fails. If you attempt to post a goods receipt against a purchase order that was never migrated, the posting is rejected. If you attempt to process an invoice that references a goods receipt that was excluded from scope, the invoice has nothing to attach to.
These are not edge cases. They are the normal operating constraints of any integrated system. And they create a problem that most migration programmes discover too late: the order in which you migrate data matters as much as the data itself.
What a dependency chain looks like
Take a single invoice in a procurement system. That invoice does not exist in isolation. It is the tip of a chain:
Invoice 5105600012 (€42,680)
└── Goods Receipt 5000023841
└── Purchase Order 4500017892 (3 line items)
├── Material MAT-9921 (Precision bearing)
├── Material MAT-4455 (Shaft seal)
├── Material MAT-7780 (O-ring kit)
└── Supplier 100234 (Müller Industrietechnik)
This chain has five levels and seven objects. The invoice at the top depends on the goods receipt. The goods receipt depends on the purchase order. The purchase order depends on three materials and one supplier. The materials and supplier are leaf nodes — they depend on nothing else.
If you are migrating this chain, the creation order is not arbitrary. It must be leaf to root:
- First, create the supplier (no dependencies)
- Then, create the materials (no dependencies)
- Then, create the purchase order (references supplier + materials)
- Then, post the goods receipt (references purchase order)
- Finally, process the invoice (references goods receipt + supplier)
Get this order wrong — attempt to create the purchase order before the supplier exists — and the creation fails. Not with a subtle data quality issue that surfaces months later. With a hard system error that stops the migration in its tracks.
Why this is harder than it sounds
In the example above, the chain is clean and linear. In a real enterprise migration, chains are tangled:
Shared dependencies. Supplier 100234 is not referenced by one purchase order. It might be referenced by fifty. Each of those purchase orders has its own goods receipts, its own invoices. If the supplier fails migration — for any reason — every one of those fifty chains is blocked. One supplier, fifty cascading failures.
Cross-chain references. A material that appears in one purchase order may also appear in a bill of materials, which is referenced by a production order, which is referenced by a cost centre allocation. The dependency graph is not a tree. It is a web.
Scope boundaries. Migration programmes often define scope by object type: "we are migrating suppliers in Phase 1, materials in Phase 2, purchase orders in Phase 3." This sounds orderly. But if Phase 1 excludes a supplier that Phase 3 needs for a purchase order, the PO fails — not because of a data quality issue, but because of a scoping decision made months earlier by a different team.
Partial migrations. A supplier is migrated, but not all of its organisational assignments come across. The supplier record exists in the target system. The purchase order references it. But when the PO is created, it fails — because the supplier has no valid purchasing organisation assignment for the relevant company code. The supplier is present. The dependency is not satisfied. The PO cannot be posted. Everything downstream is blocked.
The cascade effect
The most dangerous property of dependency chains is that failures cascade. A single root-cause failure can block dozens of downstream objects.
Consider a real scenario: a supplier has a country code that is not valid in the target system's ISO configuration. The supplier cannot be migrated cleanly. That single field-level issue cascades:
Root cause: Supplier 100456, COUNTRY = "UK" (not valid ISO 3166)
Cascade:
→ 12 Purchase Orders reference this supplier → blocked
→ 8 Goods Receipts reference these POs → blocked
→ 8 Invoices reference these GRs → blocked
Total impact: 1 field-level issue → 29 objects blocked
A programme dashboard that tracks mapping coverage would show all 29 of these objects as "mapped." The supplier has a target. The purchase orders have targets. The goods receipts and invoices have targets. Everything is green.
But nothing works. The chain is broken at the root, and every object that depends on it — directly or transitively — is blocked. The dashboard cannot see this because the dashboard tracks fields, not chains.
What chain-complete verification means
We use the term dependency-chain integrity to describe a specific property: every object in the target system has all of its upstream dependencies present, valid, and proven.
This means:
Every supplier referenced by a purchase order must exist in the target — with all required organisational assignments. Not just the supplier master record. The company code assignment. The purchasing organisation assignment. The payment terms. The reconciliation account. If any of these are missing, the PO that references the supplier will fail.
Every material referenced by a purchase order must exist in the target — with a valid configuration for the relevant plant. Not just the material master. The plant-specific data. The storage location. The valuation class. If the material exists but lacks a valid plant assignment, the PO line item referencing it cannot be created.
Every purchase order referenced by a goods receipt must exist in the target — and must be in a state that allows goods receipt posting. A PO that was migrated but is blocked or incomplete cannot receive goods. The GR attempt will fail even though the PO technically exists.
Every goods receipt referenced by an invoice must exist — and must be in a state that allows invoice verification. The three-way match (PO, GR, invoice) is enforced by the target system. Missing any leg of the match causes the invoice to go to exception.
Checking all of this requires walking the chain from top to bottom, verifying each link, and computing the cascade impact of every failure. This is not something a mapping spreadsheet can do. It requires a graph-aware engine that understands the structural relationships between object types.
Creation order: leaf to root
The correct migration order is always leaf to root. Objects with no dependencies are created first. Objects that reference them are created next. And so on up the chain.
For a procurement chain:
Order Object Type Dependencies API / Method
─────────────────────────────────────────────────────────────────
1 Suppliers None (leaf) Business Partner API
2 Materials None (leaf) Product / Material API
3 Purchase Orders Suppliers + Materials Purchase Order API
4 Goods Receipts Purchase Orders Material Document API
5 Invoices GRs + Suppliers Invoice Verification API
6 Payments Invoices Payment API
Within each level, records can be processed in parallel — all suppliers can be created simultaneously, because no supplier depends on another supplier. But across levels, the ordering is strict: no purchase order can be created until its supplier and materials exist.
This ordering is not a recommendation. It is a structural constraint enforced by the target system's referential integrity. Violate it and the system rejects the record. Respect it and the chain is built correctly from the foundation up.
What this means for your migration
If your migration programme is organised by object type rather than by dependency chain, you may be building the upper floors before the foundation is complete. This is not a criticism of the programme team — it is a structural risk that most planning approaches do not account for, because most planning is done in spreadsheets, not in graphs.
The questions worth asking:
Have we mapped the dependency chain for every object in scope? Not just which objects are included, but which objects they depend on — and whether those dependencies are also in scope.
Do we know the cascade impact of every known issue? If a supplier has a data quality problem, how many purchase orders does it affect? How many goods receipts? How many invoices? The blast radius of a single root-cause failure can be enormous, and it is invisible without chain-aware analysis.
Are we creating objects in the correct structural order? If suppliers are in Phase 1 and purchase orders are in Phase 3, is every supplier that Phase 3 needs actually included in Phase 1? Has anyone checked?
Are organisational assignments complete? A supplier record in the target is not the same as a usable supplier. The purchasing organisation, company code, payment terms, and reconciliation account all need to be present. A supplier that exists but lacks these assignments will block every PO that references it.
These are structural questions, not data quality questions. They cannot be answered by profiling individual records. They require walking the chain.
How we approach this
At Migration Proof, dependency chain analysis is the second step in our pipeline — immediately after data ingestion, before any transformation is attempted. Our chain-walk engine expands a set of invoices into the full dependency graph: every goods receipt, every purchase order, every material, every supplier. It deduplicates shared dependencies (one supplier referenced by fifty POs is extracted once, not fifty times). It computes the creation order. And it identifies every point where the chain is incomplete — a missing supplier, a missing organisational assignment, a missing material plant record.
When the bijective proof runs in the subsequent step, it operates on the full chain — not on isolated objects. A supplier that fails the proof is not just flagged as a supplier issue. Every PO, GR, and invoice that depends on it is automatically flagged with a cascade reference back to the root cause. The programme team does not need to trace the chain manually. The engine has already done it.
The result is a dependency map that shows exactly which objects are safe, which are blocked, and which root-cause issues would unblock the most downstream objects if fixed first. Fix the supplier's country code, and twenty-nine objects that were blocked become unblocked. That is the kind of prioritisation that transforms a remediation effort from "fix everything" to "fix two things and seventy-five percent of your problems resolve."
Our first release covers the full procurement chain — suppliers, materials, purchase orders, goods receipts, and invoices. These are the objects where dependency chains are longest and cascade failures hit hardest. From there, we will extend to finance, controlling, sales, and beyond.
migrationproof.io is launching shortly. The next article in this series covers precondition validation — the formal gate that stops bad data before it enters the transformation pipeline.
A note from us
Migration Proof is an AI-native operation. Five specialised AI personas run the chain walk, precondition checks, transformation, proof, and reporting. Behind them, twenty-five years of enterprise system experience shaped every rule they apply.
We are mostly agents — and we are proud of that, because agents prove every record, not a two percent sample. When you write to us, a human replies.
hello@migrationproof.ioWe read every message. We reply to every question.