The reference architecture behind a disciplined SAP-to-D365 data migration — extractor, canonical model, transformer, loader, reconciler — the governance that keeps 717 field mappings honest, the load-sequencing engine behind the eight-wave plan, and the fifteen operational-hardening controls that separate a script from a production-grade engine.
The previous chapter set the programme's shape: seven stages, an inventory discipline, and the SAP-specific traps that cause the most expensive failures. This chapter goes one layer down, into the engine that actually moves the data — because "we wrote some Python that reads SAP tables and writes DMF packages" and "we built a governed…
The reference architecture is a straight line with five named stages, each with a specific job and a specific reason it cannot be skipped:
Reading SAP without disturbing the live system is a genuinely different problem from reading it once for a one-time report, and the reference architecture treats the three pathways as deliberately distinct tools for distinct volume and change-rate profiles, not interchangeable options.
SAP's organisational hierarchy — client, company code, controlling area, plant, storage location, sales organisation — is deep. D365's is flatter: legal entities, sites, warehouses and financial dimensions.
Where the canonical model governs values, the transformation matrix governs fields. Each of the 14 business objects in scope has its own field-level matrix, one CSV per object, with a fixed column set: source table and field, source type, target entity and field, target type, the transformation rule itself, a reference to a canonical…
The Data Management Framework is built around five core concepts worth knowing by name, because the vocabulary recurs constantly once a programme is live: a Data Entity is the de-normalised, business-logic-validated abstraction over one or more physical tables (Customers V3, for instance);
Dry-run mode runs the entire pipeline — extraction through Bronze, Silver and Gold, transformation, and packaging — against fixture data, with no write to F&O at all, and checks the resulting Gold output against a known-correct expectation.
Fifteen specific controls separate a working prototype from an engine trustworthy enough to run a live cutover. Each closes one concrete risk.
Not every requirement that looks like "we need custom engine code" actually is one, and the honest answer changes what a programme spends its engineering time on.
A migration engine earns the word "engine" through architecture and operational discipline, not through the number of Python files it contains.