A Salesforce data migration checklist has six stages. Map every field, audit the data, load parents before children, dry run in a sandbox, reconcile the results, then plan the cutover and rollback.
Data migration is the one-time move of records from an old system into Salesforce, with their links intact. Clientell AI, the AI Salesforce admin, runs the pre-load checks and reconciliation queries for you. A free Salesforce health check shows data quality problems in read-only mode before you load anything. If data is one part of a bigger project, pair this with the Salesforce implementation checklist.
Why do Salesforce data migrations fail?
Migrations rarely fail because of the tool. They fail in four repeatable ways, each one visible in the org after go-live.
- A field was never mapped. A legacy free-text "Account Manager" field gets missed, and one team's report breaks after go-live.
- Load order broke the links. Contacts loaded before Accounts land with a blank
Contact.AccountId. The org looks fine, but those Contacts attach to nothing. - Nobody reconciled. The success file looked long, so everyone moved on. Weeks later, finance finds the closed-won total is wrong.
- There was no rollback plan. Salesforce has no "undo last load" button. Without the created IDs and a backup of overwritten fields, you can only patch forward.
Each stage below prevents one of these failures.
Stage 1: How do you map fields and audit the data?
Build the field map from the source side
Write one row per source field, not per target field. Then every skipped field is a recorded choice, not a surprise. Each row holds:
- Source object, field, data type and length
- Target field API name, such as
Account.Industry, with type, length and required flag - The transform rule: trim, join, date format or value remap
- Who signed off, and where dropped fields go (archive or staging)
Type mismatches cause most of the pain. Long text into a shorter field fails or gets cut. Date-times shift unless you convert them to UTC (Coordinated Universal Time). A restricted picklist rejects every value that is not on its list.
Add an External ID to every object
This is the most important choice in the plan. On each target object, create a text field and tick External ID and Unique in its field attributes. Load the source system's key into it, for example Account.Legacy_Id__c.
- Reruns become safe. An upsert on the External ID updates the record instead of making a copy.
- Links resolve without an ID map. Data Loader can fill a lookup by matching the parent's External ID.
- Rollback gets a handle. You can find every record this migration created.
Audit the data before it reaches Salesforce
Cleaning in the source is cheaper than cleaning in Salesforce later. Run these checks and fix what they find upstream.
- Duplicates: email for Contacts, website domain for Accounts.
- Required-field gaps: count rows that would fail a required field or validation rule.
- Picklist values: compare every source value with the target list.
- Orphans: child rows whose parent key is missing from the parent extract.
- Owners: every record needs an active user as
OwnerId. Decide where departed staff's records go. - Encoding: non-UTF-8 characters and stray line breaks cause many "unexplained" failures.
Our Salesforce data quality audit covers the same checks for data already in your org.
Stage 2: What order should you load objects in?
A child can't point to a parent that does not exist yet. Set up users, record types and picklists first. Then load in this order.
| Step | Object | Depends on |
|---|---|---|
| 1 | Account | Users (owners) |
| 2 | Contact | Account |
| 3 | Product2 and PricebookEntry | Price books |
| 4 | Opportunity | Account |
| 5 | OpportunityLineItem | Opportunity and PricebookEntry |
| 6 | Case | Account and Contact |
| 7 | Custom objects | Their own parents |
| 8 | Task and Event | Almost everything above |
| 9 | Notes and files | The records they attach to |
Two patterns need a second pass. For Account hierarchies, load every Account with ParentId blank, then update ParentId once all exist. For circular links, such as an Account lookup to its main Contact, load both, then update the lookup.
Stage 3: How do you run the load safely?
Dry run in a sandbox, twice
The first run finds broken mappings and failing rules. The second run, after fixes, gives your timing and your reconciliation baseline. A Developer sandbox checks mapping, but only a Full or Partial Copy sandbox shows timing at real volume.
Turn off what will fight the load
Before a bulk load, switch these off and write each one on a re-enable list:
- Validation rules that legacy data can't meet
- Record-triggered flows and Apex triggers on the objects you load
- Assignment rules, auto-response rules and duplicate rules
- Outbound email: in Setup > Deliverability, set the access level to "System email only" (deliverability settings)
Want to keep the original created dates? Turn on the "Set Audit Fields upon Record Creation" permission before the load, not after.
Pick the right tool
Salesforce's guide to choosing an import method sets clear record limits.
| Tool | Records per job | Objects | Best for |
|---|---|---|---|
| Data Import Wizard | Up to 50,000 | Accounts, contacts, leads, solutions, campaign members, custom objects | One-off lists in the browser |
| Data Loader | Between 5,000 and 5 million | All standard and custom objects | Most migrations, with export and delete |
| ETL (extract, transform, load) tool | Larger or repeated loads | All, through the APIs | Heavy transforms and a staging area |
See the Data Loader complete guide and the Data Loader vs Data Import Wizard comparison for setup.
Set batch size and avoid lock errors
Data Loader's batch size limit is 200 records with the SOAP API and 10,000 with the Bulk API. Bigger batches run faster, but a batch that hits a timeout fails as a whole. Use smaller batches on objects with heavy triggers. The Bulk API limits page lists the daily caps.
Row lock errors happen when two batches update children of the same Account at once. Sort the file by parent ID so siblings land in one batch. If the error persists, switch to serial mode. Keep every success and error file, since the success file is your rollback handle.
Stage 4: How do you check the load worked?
A finished load is not a correct load. Reconcile on three checks.
- Counts. Compare the source extract, the success file and the org, per object. Then group by owner, record type and year, because a matching total can hide an empty group.
- Sums. Compare totals of money fields. Sum
Opportunity.AmountbyStageNameand close quarter, since finance checks that number first. - Orphans. Query for children with empty parents, for example
SELECT Id FROM Contact WHERE AccountId = null. Then check that roll-up summary fields show the right totals.
Next, spot-check by hand. Pick records on purpose: your largest Account, the deepest hierarchy and a record whose owner changed. Ask a business user to review records they know well. They catch a status that mapped to a valid but wrong value.
Stage 5: How do you run the cutover?
Cutover is a timed sequence, not a single event. Announce the write freeze early, more than once, with exact times.
- Freeze writes in the source system.
- Take the final full extract.
- Export the target org's current data, if it is not empty.
- Run the final load in the agreed order.
- Run the reconciliation checks from your sandbox rehearsal.
- Turn validation rules, flows, triggers, assignment rules and email back on.
- Log in as a sample user from each profile and check what they can see.
- Make the go or no-go call against criteria written before the day.
- Open the org, with a named support channel for day one.
If the business can't stop, plan a delta load. Upsert records changed after the main extract, matched on External ID, with a fixed cutoff time and a named owner.
Stage 6: How do you roll back a Salesforce data load?
Rollback in Salesforce is rarely a clean undo. What you can reverse depends on what the load did.
- Inserts: feed the success file back to Data Loader as a delete. Delete in reverse load order, since some parent deletes remove their children too.
- Updates: reversible only if you exported the old values first, keyed by record ID. Field History Tracking covers only the fields you chose to track.
- Side effects: emails sent and data pushed to other systems during the load can't be recalled.
Agree rollback triggers in writing before cutover. Typical ones are a count gap on a core object, a mismatch in a money total, or users seeing records they should not. A handful of failed rows with a known fix is not one of them; patch those forward. Rehearse the rollback once in the sandbox.
What is the full checklist?
| Stage | Done when |
|---|---|
| Map | Every source field has a row and a sign-off |
| External IDs | A unique External ID exists on every object |
| Audit | Duplicates, gaps, picklists and owners fixed upstream |
| Load order | Sequence written, second passes planned |
| Dry runs | Two sandbox runs, timing recorded |
| Automation | Re-enable list written, email set to system only |
| Reconcile | Counts, sums and orphan queries all match |
| Cutover | Freeze announced, go or no-go criteria signed |
| Rollback | Old-value backup taken, rollback rehearsed |
Try it in Clientell AI: "Find Contacts with no Account, Opportunities with no Amount, and duplicate Accounts by website, and show the counts before I load." Start the 14-day trial, no card. It reads your org in read-only mode, builds fixes in a sandbox, and asks before it changes anything in production. See how Clientell AI keeps your org safe. For hands-on help, our Salesforce implementation services team runs migrations with this checklist.
Common questions about a Salesforce data migration checklist
What is the right load order for a Salesforce migration?
Parents before children. Load Accounts, then Contacts, then Opportunities and line items, then Cases, custom objects, activities and files.
Why use an External ID field in a migration?
It stores the old system's key on each record. Upserts on it make reruns safe, and it shows exactly which records the migration created.
Should you use Data Loader or the Data Import Wizard?
Use the Data Import Wizard for up to 50,000 records on supported objects, per Salesforce's import method guide. Use Data Loader for any object, for larger loads, and when you need export or delete.
Can you undo a Salesforce data load?
Partly. You can delete inserted records using the success file. Updates can only be reversed from a backup of the old values you took first.
How many dry runs does a migration need?
Two. The first finds problems, and the second confirms the fixes and gives you timing for cutover.
Sources
Salesforce documentation
- Choosing a Method for Importing Data
- Configure Data Loader
- Bulk API and Bulk API 2.0 Limits and Allocations
- Custom Field Attributes
- Sandboxes: Staging Environments for Customizing and Testing
- Deliverability settings
Last reviewed October 2026
Last updated: October 22, 2026




