A Salesforce data migration succeeds when you decide what to move before you move anything, clean it in the source, map every field, load objects in dependency order using external IDs, and prove the result with reconciliation before users log in. Most failed migrations skipped the test loads or the reconciliation. The checklist below follows the order we work in, from scoping through the week after cutover.
1. Inventory and scope
Start with a list of every source: the old CRM, marketing and support tools, spreadsheets, and the ERP if it holds customer data. For each one, record the objects, the approximate volume, who owns the data and how you will extract it. Then make deliberate decisions about what not to bring. A new org is the cheapest chance you will ever get to leave clutter behind.
- List every source system and spreadsheet, with an owner for each.
- Decide how much history to move: all closed deals, or only a recent window with older records archived.
- Leave behind records with no activity and no revenue history, unless a regulation requires them.
- Retire fields nobody filled in or reported on; do not recreate them in Salesforce.
- Decide where attachments, emails and notes go, since they are often the largest and slowest part.
- Agree who signs off that the migrated data is correct.
2. Cleanse and deduplicate at the source
Fix data before it moves, not after. Standardize company names, states, countries and phone formats; map free-text values to the picklist values Salesforce will enforce; and merge duplicates so each customer arrives once. Cleaning in the source or in a staging spreadsheet is easier than cleaning inside a live org where records already have related activity. Our guide to cleaning up duplicate data in Salesforce covers survivorship rules and merge order in detail.
Cleanup often matters as much as the move itself. A medical-device company we worked with removed 970+ invalid prospects as part of getting its marketing platform working again; bringing them along would only have carried the problem into the new system.
3. Field mapping and load order
Build a mapping document with one row per source field: the target object and field, any transformation, the default when the source is blank, and the person who approved it. Mapping forces the design conversations that matter, such as whether a status field becomes an opportunity stage, a record type or both.
Parent records must exist before the children that point to them, so load in dependency order. A typical sequence looks like this:
| Order | What to load | Depends on |
|---|---|---|
| 1 | Users, roles and territories | Nothing; owners must exist before records |
| 2 | Products, price books and price book entries | Users |
| 3 | Accounts, including parent accounts before child accounts | Users |
| 4 | Contacts | Accounts |
| 5 | Leads | Users; load after contacts so matches can be checked |
| 6 | Opportunities, then contact roles and line items | Accounts, contacts, price book entries |
| 7 | Cases and custom objects | Accounts, contacts and any parent custom objects |
| 8 | Tasks, events, notes and files | Whatever record they relate to |
4. IDs, external IDs, owners and automation
Salesforce creates new record IDs on insert, so relationships from the old system break unless you plan for them. Add a legacy ID field on each migrated object and mark it as an external ID. Loads can then upsert on that field and set lookups by referencing the parent's legacy ID, and reruns update records instead of duplicating them. Keep these fields after go-live; they are how you trace any record back to its source.
Owners need the same care. Map every source user to a Salesforce user, decide who inherits records from people who have left, and load inactive owners only if history requires it. If original created dates matter for reporting, Salesforce lets an administrator enable setting audit fields on record creation for the migration user. Finally, switch off or bypass validation rules, Flows, assignment rules and email alerts during the load, so customers do not receive a welcome email for a relationship that started years ago.
5. Test loads and reconciliation
Run at least one full test load into a sandbox, ideally a full or partial copy with production-like configuration, and time it. The timing tells you how long the cutover window needs to be. Then reconcile the result against the source before anyone calls it done:
- Record counts per object match the source, minus the records you chose to leave behind.
- Totals such as opportunity amounts by year and stage match the source.
- No orphans: every contact has an account and every opportunity has an owner.
- Picklists hold only valid values, and required fields are populated.
- A sample of records chosen by the business owner is checked field by field against the source.
- Error logs from every load are reviewed and every rejected row is fixed or explained.
Repeat the test load after fixes. Users who test on migrated data find mapping problems that nobody spots on sample records.
6. Cutover, freeze window and post-migration checks
Agree a freeze window during which the old system is read-only, announce it early, and plan a delta load for anything created between the final extract and the freeze. Keep the old system readable for a set period after go-live so people can check history. Once the production load finishes, rerun the reconciliation, reactivate automation, confirm integrations point at the new records, and give users a way to report data problems during the first weeks.
Staged rollouts reduce the risk further. A cybersecurity company we worked with moved 2,300 accounts and contacts out of its old CRM with a crawl-walk-run rollout and went live with core functionality in roughly 6-8 weeks. A compliance-software company moved accounts, contacts, leads, opportunities, tasks and activities from HubSpot to Salesforce in 4-6 weeks. In both cases the migration was planned as part of the implementation, not bolted on at the end.
