CRM Data Migration Guide: Mapping, Cleansing, Deduplication, and Validation

How to move customer data without losing identities, relationships, business meaning, or the ability to prove that the migration is complete.

Written byTespir Data Engineering Team
Published
Reading time19 minutes
In brief

A reliable CRM migration is a controlled data-engineering program, not a one-time import. Mapping, cleansing, deduplication, relationship sequencing, reconciliation and rollback evidence must be designed before production cutover.

Migration controls at a glance

Migration contractDocument every source field, target field, transformation, identifier, relationship rule, and exception before loading production data.
Identity controlPreserve source IDs and maintain a crosswalk from source records to target records for repeatability, relationships, and rollback.
Quality controlNormalize and deduplicate before the final load, then validate again against target constraints and business rules.
Proof of completionClose the project with a reconciliation report that explains every extracted record, every target result, and every unresolved exception.

A CRM migration is not successful because an import job finished. It is successful when the target system contains the correct records, the correct relationships, the correct business meaning, and an auditable explanation for every exception.

Most migration failures are not caused by an inability to insert rows. They are caused by incorrect assumptions about identity, field semantics, relationship order, duplicate ownership, and what the word “complete” actually means.

A technically successful import can still create serious operational damage:

  • Contacts are loaded but associated with the wrong companies.
  • Historical IDs are discarded, making future updates impossible.
  • Custom fields are converted to strings and lose controlled values.
  • Duplicate companies fragment revenue, activity, and ownership history.
  • Blank source values overwrite valid target data.
  • Users begin working in the new CRM while a final delta is still missing.
  • The project team can report imported rows but cannot reconcile them to the source.
Treat CRM migration as a controlled data product with contracts, state, observability, and recovery—not as a one-time file upload.

Define acceptance criteria before extraction

The migration plan should state what must be true at cutover. Useful acceptance criteria include:

  • Every eligible source record has a classified migration outcome.
  • Every migrated record retains a stable source-system identifier.
  • Required parent-child relationships are present and valid.
  • Controlled values conform to target options and pipelines.
  • Duplicate decisions are documented and reproducible.
  • Failed records are isolated with actionable error reasons.
  • Created and updated records can be reversed safely.
  • Business owners sign off on the reconciliation report.

Build a source-to-target mapping contract

Source-to-target mapping is not just a spreadsheet showing that company_name maps to Account.Name. It is an executable specification for how data changes meaning as it moves between systems.

For each field, the contract should record:

  • Source system, object, table, and column.
  • Target provider, object, and field.
  • Source and target data types.
  • Transformation and normalization rules.
  • Null, blank, and default behavior.
  • Required and writable status.
  • Controlled-value mapping.
  • Validation rules and rejection behavior.
  • Data owner and approval status.
Source
Target
Transformation
Rule
organizations.legal_name
Account.Name
Trim; Unicode normalization
Reject when empty after normalization
organizations.lifecycle
Customer_Status__c
Enumeration map
active → Customer; unknown values quarantined
contacts.company_id
AccountId
Crosswalk lookup
Parent must resolve before contact load
contacts.email
Email
Trim; validate structure
Do not invent or repair ambiguous addresses

Model null, blank, and missing values separately

A missing column, a database NULL, an empty string, and a user intentionally clearing a value are not necessarily the same event.

The contract should define one of four actions for every nullable field:

  1. Preserve target: do not send the field when the source has no authoritative value.
  2. Clear target: explicitly remove the existing target value.
  3. Default: apply an approved business default.
  4. Reject: quarantine the record because the field is required.

Without this distinction, an update migration can unintentionally erase valid target data.

Store mapping configuration as versioned data

The mapping used for the pilot should be the same mapping used for production unless a reviewed version replaces it. A machine-readable contract makes the migration repeatable and testable.

// Simplified example
{
  "migrationRunId": "crm-2026-08-06-wave-02",
  "entity": "company",
  "source": {
    "table": "organizations",
    "primaryKey": "organization_id"
  },
  "target": {
    "provider": "salesforce",
    "object": "Account",
    "externalIdField": "Legacy_Organization_ID__c"
  },
  "fields": [
    {
      "from": "legal_name",
      "to": "Name",
      "transforms": ["trim", "unicode_nfkc"],
      "required": true
    }
  ],
  "relationships": [
    {
      "from": "parent_organization_id",
      "to": "ParentId",
      "resolveBy": "Legacy_Organization_ID__c",
      "onMissing": "quarantine"
    }
  ]
}

Preserve identifiers and rebuild relationships deliberately

Identifiers are the backbone of a safe migration. The target CRM will generate new internal record IDs, but the migration still needs a stable way to recognize the same real-world record across repeated loads, deltas, retries, and rollback operations.

Keep three identities separate

  • Source primary key: the record identifier in the legacy system.
  • Target record ID: the provider-generated identifier in the new CRM.
  • Business key: a meaningful identifier such as contract number, customer number, or verified external account ID.

Do not replace the source key with a mutable business attribute such as company name or phone number. Names change. Domains are sold. Email addresses are reassigned. A migration key should remain stable.

Create a crosswalk table

A crosswalk records how source records correspond to target records. It should be persisted outside temporary import files.

source_system,source_object,source_id,target_provider,target_object,target_id,migration_run_id,outcome
legacy_crm,organization,ORG-10482,salesforce,Account,001xx00000AbCDe,crm-2026-08-06-wave-02,created
legacy_crm,contact,CNT-78311,salesforce,Contact,003xx00000XyZ12,crm-2026-08-06-wave-02,updated

The crosswalk supports:

  • Idempotent retries and upserts.
  • Parent and child relationship resolution.
  • Delta migrations after the initial load.
  • Traceability from target records back to source records.
  • Rollback and repair operations.
  • Post-migration support investigations.

Load records in dependency order

Relationships should be modeled as a directed graph. Parent records must normally be available before child lookups can be resolved.

Reference data

Users, owners, teams, pipelines, currencies, products, and controlled values required by business records.

Root records

Companies, accounts, households, or other top-level entities that do not depend on migrated parents.

Child records

Contacts, locations, subscriptions, opportunities, tickets, and custom objects resolved through the crosswalk.

Junctions and associations

Many-to-many relationships, association labels, team memberships, and custom relationship objects.

Activities and history

Notes, calls, meetings, tasks, emails, and other records whose parents must already exist.

Engineering principle

Do not resolve every relationship with a live API search by name. Resolve against indexed external IDs or a local crosswalk. Name-based lookups are slower, ambiguous, and difficult to reproduce.

Handle unresolved relationships explicitly

When a parent cannot be resolved, choose an approved policy:

  • Quarantine the child record and retry after the parent is corrected.
  • Load the child without the optional relationship and record a repair task.
  • Associate the child with a controlled placeholder only when the business has approved that behavior.
  • Reject the record when the relationship is mandatory.

Silently attaching a record to the first approximate match is not a migration strategy.

Inventory and create custom fields before loading data

Custom fields carry business meaning that standard schemas do not capture. They often contain segmentation, commercial status, compliance attributes, legacy identifiers, implementation details, or industry-specific information.

Before creating target fields, classify each source field:

  • Mapped: a compatible target field already exists.
  • New custom field: the value is required and needs a target property.
  • Transformed: several source fields combine into one target field, or one source field splits into several target fields.
  • Archived: preserved outside the operational CRM for history or compliance.
  • Discarded: intentionally excluded with business-owner approval.

Check semantic compatibility, not only type compatibility

Two text fields may still be incompatible. One may contain free text while the other expects a controlled status. A numeric field may represent currency in one system and a percentage in another.

Review:

  • Internal field name and visible label.
  • Data type and field type.
  • Maximum length and numeric precision.
  • Enumeration options and internal values.
  • Required, calculated, read-only, or unique behavior.
  • Visibility and permissions.
  • Dependencies on workflows, validation rules, or automation.

Do not create a custom field for every legacy column

A migration is an opportunity to reduce data debt. Recreating every unused legacy field transfers the old system’s complexity into the new one.

Require an owner and a defined use case for each new field. When historical information must be retained but does not belong in the operational interface, store it in an archive or governed migration snapshot rather than crowding the CRM.

Normalize data without changing its meaning

Normalization makes equivalent values comparable and target-compatible. It should be deterministic, documented, and reversible where possible.

Common normalization rules

  • Trim leading and trailing whitespace.
  • Normalize Unicode representation before comparison.
  • Standardize line endings and remove control characters that the target cannot accept.
  • Parse dates with an explicit source timezone; store UTC where the target expects an instant.
  • Normalize phone numbers only when country context is available.
  • Map country, state, language, currency, and lifecycle values to approved canonical codes.
  • Convert boolean variants such as Y, 1, and true through an explicit lookup table.
  • Preserve leading zeros in identifiers by treating them as strings.
Avoid destructive cleaning

Do not “fix” ambiguous information automatically. A malformed email, incomplete phone number, or uncertain country code should be flagged rather than converted into a plausible but incorrect value.

Email normalization requires care

Remove surrounding whitespace and validate the basic structure. Domain names can be compared case-insensitively. Do not assume that changing the case of every local part is always semantically neutral unless the target CRM and the organization’s identity rules explicitly make that assumption.

Dates need a timezone policy

A source value such as 2026-08-06 09:00 is incomplete unless its timezone is known. The migration should record whether the value represents:

  • An absolute instant that should be converted to UTC.
  • A local business time that should retain timezone context.
  • A date-only value that must not shift when converted.

Keep raw and normalized values during staging

The staging model should preserve the original source value next to the normalized value and the applied rule. This makes review, debugging, and rollback possible.

{
  "sourceValue": "  ACME Holdings  ",
  "normalizedValue": "ACME Holdings",
  "rulesApplied": ["trim", "unicode_nfkc"],
  "validationStatus": "valid"
}

Detect duplicates before they become target records

Deduplication is not simply deleting rows with the same email address. It is the controlled process of deciding whether records represent the same entity and, when they do, which values and relationships survive.

Start with deterministic identifiers

The safest match keys are stable source IDs, existing target IDs, verified external IDs, contract numbers, or properties configured to be unique.

Use deterministic matching before fuzzy matching:

  1. Exact source-system or migration ID.
  2. Exact approved business key.
  3. Exact provider-supported unique property.
  4. Composite exact key, such as normalized domain plus country.
  5. Fuzzy candidate scoring for records that remain unresolved.

Generate candidates before calculating similarity

Comparing every record with every other record is expensive and produces noise. Use blocking keys to form candidate groups—for example, normalized domain, phone suffix plus country, postal code plus name prefix, or phonetic name group—then calculate similarity inside those groups.

Separate candidate detection from merge decisions

A duplicate engine should return evidence, not only a binary answer. A useful candidate record includes:

  • Matched keys and normalized values.
  • Similarity scores by field.
  • Conflicting fields.
  • Relationship and activity counts.
  • Recommended survivor.
  • Decision source: automatic rule or human review.

Define survivorship at field level

When two records are merged, the survivor is not always the row with the newest update timestamp. Define rules such as:

  • Prefer verified values over unverified values.
  • Prefer the system of record for regulated attributes.
  • Prefer the most recently confirmed contact details.
  • Preserve the earliest creation date.
  • Union non-conflicting relationships and activity history.
  • Escalate contradictory high-value fields for review.
Safe automation

Auto-merge only high-confidence matches supported by deterministic evidence. Route medium-confidence candidates to review, and keep low-confidence records separate. A false merge is usually harder to repair than a missed duplicate.

Deduplicate against both source and target

The migration must detect:

  • Duplicates inside the source extract.
  • Duplicates created by combining multiple source systems.
  • Records that already exist in the target CRM.
  • Records that were inserted by an earlier migration wave.

This is why the crosswalk and migration-run history are part of the deduplication design.

Use a phased migration instead of one irreversible load

A staged approach reduces the number of unknowns introduced at the same time. Each phase should have entry criteria, exit criteria, reconciliation, and a go/no-go decision.

Profile and snapshot

Capture source counts, distributions, null rates, duplicate candidates, relationship integrity, and a reproducible source snapshot.

Prepare the target schema

Create approved custom fields, unique identifiers, pipelines, controlled values, owners, and relationship definitions before record loading.

Run a representative pilot

Use records that include custom fields, duplicates, large histories, missing parents, unusual characters, and validation edge cases—not only clean examples.

Load foundational waves

Migrate reference data and parent objects, reconcile them, and freeze their crosswalk before loading dependent records.

Load relationships and history

Migrate children, many-to-many associations, activities, and attachments in controlled batches with per-record results.

Capture and apply the delta

Extract records changed since the snapshot, apply the same mapping and deduplication rules, and reconcile the delta separately.

Cut over and verify

Switch operational ownership, run smoke tests, validate critical workflows, and monitor errors before releasing the migration team.

Choose batch boundaries that support repair

Batches should be small enough to isolate errors but large enough to use provider bulk APIs efficiently. Useful boundaries include object type, business unit, geography, source system, migration wave, and dependency group.

Every batch should carry a stable migration_run_id and batch_id. Do not rely only on provider job IDs; retain your own execution ledger.

Control automation during the load

CRM workflows, triggers, assignment rules, notifications, and integrations can multiply the effect of imported records. Before migration, decide which automations should:

  • Remain active and be tested as part of the migration.
  • Be temporarily disabled.
  • Ignore records carrying a migration marker.
  • Run only after reconciliation and cutover.

Document every temporary change and its restoration owner.

Design rollback before the first production write

Large CRM migrations are rarely one atomic transaction. “Rollback” usually means a controlled set of compensating operations based on a complete execution ledger.

Important distinction

Aborting an unfinished import job is not the same as reversing records that were already created or updated. The migration plan must cover both.

Record enough state to reverse each operation

For every attempted record, store:

  • Migration run and batch identifiers.
  • Source object and source ID.
  • Target object and target ID.
  • Operation: create, update, associate, delete, or skip.
  • Provider response and error details.
  • Before-image for fields changed by an update.
  • After-image or canonical payload hash.
  • Relationship operations performed.
  • Timestamp and mapping version.

Use different rollback actions for different outcomes

  • Created record: delete or archive only the captured target ID when the record has not acquired valid post-cutover activity.
  • Updated record: restore the before-image; do not delete the record.
  • Created relationship: remove the association after dependent records are handled.
  • Merged duplicate: restore only when the provider and retained history make separation reliable; otherwise treat the merge as a high-risk, separately approved operation.
  • Failed or unprocessed record: no target reversal is required, but the outcome must remain in the ledger.

Reverse in dependency order

Rollback normally runs in the opposite order of migration:

  1. Stop new writes and downstream automation.
  2. Remove newly created associations and child records.
  3. Restore updated child records.
  4. Remove newly created parent records.
  5. Restore updated parent records.
  6. Reconcile the target against the pre-migration snapshot.

Do not rely exclusively on provider restore features

Provider history and restore tools can be valuable safeguards, but availability, retention windows, supported objects, and permissions differ. Your own before-images, target IDs, crosswalk, and execution ledger remain the reliable basis for a migration rollback.

Close with a reconciliation report, not a success message

A reconciliation report proves how source data became target data. It should be understandable by engineering, operations, data owners, and project sponsors.

Reconcile every record into one outcome

eligible records = extracted records − approved exclusions − duplicate losers
attempted records = created + updated + intentionally skipped + failed + unprocessed
unresolved records = failed + unprocessed + quarantined relationship repairs

The exact categories may differ, but they must be mutually understandable and should not hide records between stages.

Report at object and wave level

ObjectExtractedExcludedDedupedCreatedUpdatedFailedUnresolved linksStatus
Companies42,1846121,90431,8227,834120Review 12
Contacts168,9034,2189,744132,01622,841768Review 84
Deals18,440321015,9012,21800Reconciled

Illustrative figures only. Production reports should be generated from the execution ledger and provider result files.

Counts are necessary but not sufficient

Add data-quality checks that detect technically loaded but semantically incorrect records:

  • Uniqueness of migration and business keys.
  • Orphaned child and junction records.
  • Required-field null rates.
  • Distribution changes for statuses, owners, countries, pipelines, and currencies.
  • Unexpected truncation or character replacement.
  • Aggregate totals such as open pipeline value or active contract value.
  • Sample-level comparison of high-value and high-complexity records.
  • Source-to-target hashes for stable canonical subsets.

Include operational sign-off

The report should identify remaining exceptions, business impact, owners, remediation dates, and the explicit decision to proceed or hold cutover. A migration with documented low-risk exceptions may be acceptable. A migration with unexplained differences is not.

Provider-specific implementation notes

The migration framework is provider-neutral, but the execution layer must respect each CRM’s identity, bulk processing, relationship, and error-reporting mechanisms.

Salesforce

For current Summer ’26 environments, Salesforce documentation lists API version 67.0. Use object describe metadata before mapping and Bulk API 2.0 for asynchronous large-volume ingest.

  • Discover fields with GET /services/data/v67.0/sobjects/Account/describe.
  • Create ingest jobs through POST /services/data/v67.0/jobs/ingest.
  • Use external-ID upsert for repeatable loads.
  • Retrieve successful, failed, and unprocessed results and join them back to the source ledger.
  • Reference parent records through external IDs where the relationship supports it.
Salesforce Bulk API 2.0

HubSpot

HubSpot supports guided file imports and an Imports API. Its current developer documentation also exposes date-versioned CRM endpoints for properties and imports.

  • Read target property definitions before generating payloads.
  • Use Record ID, email, domain, or an approved custom unique property where supported.
  • Create and validate associations explicitly rather than assuming row order.
  • Download import errors and retain the import ID in the migration ledger.
  • Review provider restore capabilities as an additional safeguard, not the only rollback plan.
HubSpot Imports API

Microsoft Dataverse

Dataverse supports import data maps, transformation mappings, alternate keys, upsert operations, and configurable duplicate-detection rules.

  • Use alternate keys to identify rows by external-system values rather than target GUIDs.
  • Use data maps for column, lookup, and list-value mapping.
  • Ensure transformed values remain compatible with target column types.
  • Configure duplicate rules for custom tables; default coverage should not be assumed.
  • Retain import log failures in the reconciliation evidence.
Dataverse alternate keys

Salesforce result files are part of reconciliation

Bulk API 2.0 provides separate resources for successful, failed, and unprocessed rows. The order of returned rows should not be assumed to match the original upload, so include a stable source identifier in every row and reconcile by that identifier.

HubSpot unique identifiers must be chosen intentionally

HubSpot imports can create, update, and associate records. Updates require an identifier recognized by the selected object and import mode. A custom property configured for unique values can provide a stable legacy-system key when the built-in identifiers are not appropriate.

Dataverse duplicate detection depends on published rules

Dataverse can detect and merge duplicates, but custom record types require suitable duplicate-detection rules. Migration teams should not assume that every table receives useful duplicate protection by default.

Production migration checklist

  • Freeze and version the source-to-target mapping contract.
  • Profile source counts, nulls, distributions, and relationship gaps.
  • Create target fields, unique keys, options, and pipelines first.
  • Preserve source IDs in the target or crosswalk.
  • Define deterministic and fuzzy duplicate policies.
  • Approve field-level survivorship rules.
  • Test normalization using real edge cases.
  • Load parents before children and associations.
  • Tag every operation with run and batch IDs.
  • Capture before-images for every update.
  • Retain provider success, failure, and unprocessed results.
  • Run count, relationship, distribution, and aggregate checks.
  • Test rollback in a non-production environment.
  • Plan the final delta and source freeze window.
  • Assign exception owners before cutover.
  • Obtain business and technical reconciliation sign-off.

Frequently asked questions

01Should CRM data be cleaned before or after migration?

Normalize and resolve known duplicates in a staging layer before the final load, then validate again after loading. Cleaning only in the target makes the migration harder to reproduce; cleaning only before the load misses provider-side constraints and existing target records.

02What is the safest identifier for CRM upsert?

Use a stable, unique source-system or business identifier that does not change when names, ownership, contact information, or lifecycle status change. Configure it as an external or unique key where the provider supports that capability.

03Can email be used as the only contact deduplication key?

Email can be a strong identifier in some CRM configurations, but it should not be assumed to represent one permanent person in every business context. Shared addresses, reassignment, missing emails, and provider-specific uniqueness rules require a broader matching policy.

04How should custom objects be migrated?

Create and validate the target object schema first, preserve source IDs, load required parents, migrate custom records, and then create junctions or associations. Reconcile object counts and relationship integrity separately.

05Is rollback the same as deleting the import?

No. Deleting newly created records may reverse part of a migration, but updated records require their previous values to be restored. Relationships, automation side effects, merges, and post-migration user activity also require separate treatment.

06What should a CRM reconciliation report contain?

At minimum: extracted, excluded, deduplicated, created, updated, skipped, failed, unprocessed, and unresolved-relationship counts by object and wave; error categories; uniqueness and orphan checks; critical aggregate comparisons; exception owners; and sign-off status.

Final perspective

A reliable CRM migration is an identity and relationship project as much as it is a data-transfer project.

The strongest implementations share the same characteristics:

  • The mapping is explicit and versioned.
  • Source identifiers remain traceable.
  • Relationships are rebuilt through deterministic keys.
  • Custom fields are governed rather than copied blindly.
  • Normalization preserves meaning.
  • Deduplication produces evidence and controlled survivorship.
  • Migration runs in measurable phases.
  • Rollback is based on captured state.
  • Reconciliation accounts for every record.

When these controls are designed before production loading, the migration becomes repeatable, explainable, and supportable. Without them, the team may complete the import and still spend months discovering what was lost.

Technical reference points

This article is an original Tespir editorial guide. The links below point to official provider documentation used to verify current API behavior and platform capabilities as of August 6, 2026.

Tespir · Design, engineering, and QA

Plan the migration before the target CRM becomes the new source of confusion.

Tespir helps teams turn CRM migration into a controlled delivery program: source profiling, target data modeling, mapping specifications, transformation and deduplication pipelines, provider API implementation, migration dashboards, reconciliation reporting, rollback tooling, and end-to-end quality assurance.

Because our strategy, UX, engineering, integration, and QA teams work as one delivery unit, the migration controls are designed together with the administrative experience and the systems that will operate after cutover.