Moving data is easy; proving it moved is not
Writing the script that copies records between systems is usually a day. The time goes into answering the question everyone asks afterwards: is it all there, and is it right? Teams that plan only the move discover the reconciliation cost after the cutover, under pressure.
Write the reconciliation first
Before moving anything, define the checks that prove success: counts by type, totals for anything financial, a sample compared field by field, and a list of records deliberately excluded. Running these against the old system first gives you the baseline the migration must reproduce.
If you can’t describe the check that proves the migration worked, you aren’t ready to run it.
Migrate repeatedly, not once
A migration you can run many times against a copy is one you can debug calmly. Design it to be re-runnable and idempotent from the start; a one-shot script means every problem is discovered during the only attempt you get.
Decide what happens to the bad records
Every real dataset contains rows that don’t fit the new model: missing fields, impossible dates, duplicates, orphans. Decide in advance whether they are fixed, excluded, or migrated as-is, and produce a list. Silent dropping is what turns a migration into a trust incident months later.
Keep the old system readable
Retain read access to the source for a defined period after cutover. Almost every migration produces a question in the following weeks that can only be settled by looking at the original, and having it available converts a crisis into a lookup.
Cutover is an ops plan, not a deploy
Write the sequence, the freeze window, who verifies what, and the point past which you stop and roll back. This is the same reasoning as strangling a rewrite rather than replacing it wholesale — the option to stop halfway is the thing worth designing for.