The Data Migration Playbook: Moving a Legacy System Into Odoo

Data migration is the part of an implementation most likely to be underestimated and most likely to derail a go-live. This playbook is the sequence that keeps it boring.

Every implementation that replaces an existing system has to move the data. It is routinely scoped as a late, mechanical task and routinely turns out to be neither. Bad source data, ambiguous mappings, and a cutover load nobody rehearsed are how a confident go-live slips. This playbook is the sequence we follow to keep migration predictable.

Step 1: Profile the source data before promising anything

Before any mapping, look at the actual data in the legacy system. Not the schema, the data. How many customer records, and how many are duplicates. How many products, how many inactive. Are the required fields actually populated. Source data is almost always worse than the client believes, because the people describing it describe the data they use, not the decade of accumulated records behind it. Profiling first means the migration plan is built on what the data is, not on what it was assumed to be.

Step 2: Decide what does not move

Not all of it should come across. Closed records from years ago, obsolete products, contacts for companies that no longer exist: migrating them imports clutter and slows every later step. Decide, explicitly and with the client, the cutoff. What is migrated as live data, what is migrated as historical or read-only, and what is left in an archive of the old system. A smaller, cleaner migration is faster and safer at every stage that follows.

Step 3: Build the field mapping

For every record type that moves, map each source field to its Odoo destination. The mapping is where the real decisions surface: a field with no clean destination, two source fields that collapse into one, a value that has to be transformed rather than copied. Write the mapping down as a document. It is the specification the migration code implements, and the thing the client signs off on.

Step 4: Migrate in dependency order

Records have dependencies. Customers and products before orders; the chart of accounts before transactions. Sequence the migration so that every record's prerequisites already exist when it loads. Getting the order wrong produces a flood of failures that look like data problems and are really sequencing problems.

Step 5: Dry run, then validate against known totals

Run the full migration into a non-production Odoo. Then validate, and validate against numbers the client already trusts. Record counts per type. Financial totals that must tie to the legacy system to the cent. A sample of individual records checked by hand against the source. The dry run is not finished when the import completes without errors; it is finished when the validation numbers match. Expect to run it several times.

Step 6: Plan and rehearse the cutover load

The final migration happens during the cutover window, against a clock. Two things have to be known in advance: how long the full load actually takes, measured from the dry runs, and the exact state of the source at the moment of extract. Rehearse it. A migration that takes six hours when the cutover window is four is a problem you want to find in rehearsal, not at go-live.

The note for the file

A good data migration is invisible: the new system simply has the right data on day one. That invisibility is bought entirely in the steps before cutover, profiling, mapping, dry-running, validating. Skip them and the migration still happens, just live, in production, watched by everyone.