Tekunda Team

Tekunda Team

How to Run a Successful Salesforce Data Migration

How to Run a Successful Salesforce Data Migration

Short answer: a Salesforce data migration is decided in the data-quality phase, weeks before load day. Profile the source data, decide deliberately what not to move, map every field with an external ID behind it, then rehearse the cutover until it is boring. Loading is the easy part, and it is almost never what goes wrong.

Why do Salesforce data migrations actually fail?

Rarely because of the load. Data Loader, Bulk API and the ETL tools all work. Failures trace back to decisions dodged earlier:

  • No named owner for a data domain, so nobody could approve a rule.
  • Duplicates that everyone saw and nobody agreed how to resolve.
  • A source field whose meaning drifted years ago and was mapped on its label.
  • A scope that quietly became "everything", because deleting nothing felt safer than choosing.

All four are cheap to fix in week two and brutal on cutover night. That is the whole argument for front-loading data quality.

What does profiling actually mean here?

Profiling is measurement, not inspection. Before anyone writes a mapping row, produce numbers for each source object:

  • Fill rate per field. A field populated in 4% of records is not a field, it is a rumour.
  • Distinct values against the target picklist. This is where "Prospect", "prospect" and "PROSPECT " become three values and one argument.
  • Duplicate rate on the intended matching key. Measure it before you choose the key, not after.
  • Orphan rate on every relationship. Child records with no resolvable parent decide your load order and your error volume.
  • Owner resolution rate. What percentage of records map to an active Salesforce user, and who gets the rest.
  • Date ranges and outliers. Records dated 1900 or 2099 fail a validation rule at the worst moment.

The output is a short profile report. Its real job is turning opinions into numbers, so scope conversations end in a decision instead of a meeting.

What should you decide not to migrate?

This is the highest-leverage decision in the project and the one most plans skip. Every record has four possible fates, and only one of them is expensive:

  1. Migrate. It is needed operationally, in Salesforce, by a named process.
  2. Summarise. The history matters as an aggregate, not row by row. Load a rollup, not ten years of transactions.
  3. Archive. Keep it in a warehouse or export for compliance, out of the CRM.
  4. Leave it. Keep the legacy system read-only for a defined period and let people look things up.

Sensible defaults: closed records older than your reporting horizon get summarised, contacts with no activity and no reachable email get archived, and free-text fields nobody reports on do not come across at all. Every record you exclude removes mapping effort, validation failures, test cases and post-go-live support. Reduced scope is the cheapest performance improvement available.

How do you build a mapping that survives contact with the data?

One row per target field, carrying: source field, transform rule, default value, owner, the validation it must pass, and the sign-off date. A row with no owner is not a mapping, it is a hope.

Two technical decisions determine how calm the rest of the project is:

  • Put an external ID on every object you load. It carries the legacy key, so parent-child relationships resolve without Salesforce IDs, upsert makes loads idempotent, and a re-run is safe. Without it, every retry risks duplicates.
  • Choose the matching key before you write a single transform. Email, tax number, legacy ID, or a composite. The profile report tells you which of them is actually unique in your data.

Then decide, in writing, which automation is suspended during the load and who turns it back on: validation rules, triggers, flows, assignment rules, duplicate rules and email alerts. An unplanned welcome email to 40,000 migrated contacts is the classic version.

How many dry runs, and what do you measure?

Three, minimum, in a sandbox that resembles production.

  1. Shape run. Does it load at all? Field types, required fields, picklist values, record types.
  2. Correctness run. Validate relationships rather than row counts. Matching totals with broken parents is the most reassuring failure mode in this whole discipline.
  3. Timed run. Full volume, measured end to end, so the cutover window is a number you observed rather than one you estimated.

Keep every error log and treat the error rate as a trend. If run three is not materially cleaner than run one, the mapping is not converging and the go-live date is fiction.

What belongs in the cutover plan?

A cutover plan is a sequence with clock times and an owner per line, not a narrative:

  1. Freeze the source system and announce the freeze to users, not just to the project channel.
  2. Take the final delta extract.
  3. Suspend the automation on the agreed list.
  4. Load parents before children, in the declared order, in waves that isolate errors.
  5. Re-enable automation and confirm each item is back on.
  6. Run reconciliation queries: counts per object, orphan checks, spot checks on named records that business users chose in advance.
  7. Business sign-off against those named records, then go or no-go.
  8. Unfreeze, or execute the rollback.

Define rollback before cutover night, while it is a design question and not a panic. In practice: keep the legacy system authoritative and read-only until sign-off, and keep an external ID on every migrated record so a targeted delete or full re-load stays possible. Then staff the first 48 to 72 hours properly, because day-one questions reveal what the profile report missed.

We run migrations this way on client delivery, and it is part of how we have taken 16+ organisations live in production. Scoping one and want a second opinion on the data before a date is committed? Start here.

FAQ

How long does a Salesforce data migration take?

The load takes hours. The project takes as long as data-quality decisions take, which is why the timed dry run, not the plan, should set your cutover window.

Should we clean the data in the source system or during the load?

In the source where the owners are, wherever possible. Transform rules in a load script are invisible to the business and get re-litigated after go-live.

Do we need external IDs if we migrate only once?

Yes. They make retries safe, resolve relationships without Salesforce IDs, and are what makes a rollback or a targeted re-load possible later.

How much history should we bring across?

Only what a named process or report uses. Summarise the rest and archive the remainder outside the CRM: history is the most common source of scope creep here.

Related Articles