CRM migration guide

The Definitive Guide to Migrating to Salesforce

Salesforce is the platform-as-CRM destination whose migration difficulty is driven by External IDs, async loader job mechanics, and the Apex/Flow/Validation Rule stack that fires on every imported row.

22 min read 9 sections Updated May 27, 2026
Salesforce Sales Cloud
Contacts
Companies
Deals
Leads
Activities
Notes

Inside this guide

What you'll learn, section by section

  1. 01

    Why teams migrate to Salesforce

    The four shapes a Salesforce migration takes, and what makes the platform harder — or easier — than the category average.

  2. 02

    The Salesforce data model you need to map into

    Standard Objects, Custom Objects, Record Types, relationships, and the External ID upsert mechanism — the destination schema decoded.

  3. 03

    Pre-migration prep — the work before you touch Salesforce

    What must be true on the source, the destination, and across the team before the first row is loaded.

  4. 04

    Import mechanisms: Data Import Wizard and Data Loader

    Multiple mechanisms in, each with different limits, object support, and async behaviour. Picking the wrong one stalls mid-migration at scale.

  5. 05

    Mapping your data into Salesforce

    The longest section — because field mapping plus Record Type plus External ID is where almost every Salesforce migration that fails actually breaks.

  6. 06

    The pitfalls that derail Salesforce migrations

    Specific failure modes — ranked by impact, each tied to the exact Salesforce mechanism that breaks.

  7. 07

    Validation and cutover

    What to verify after the loader finishes, in what order — and how to fail safely when Triggers ate a chunk.

  8. 08

    Migration partners and tools

    Summit and Crest Salesforce Partners, iPaaS vendors, specialist migration shops — what each is good for and how to choose.

  9. 09

    Frequently asked questions

    The questions every Salesforce migration team works through before they sign the scope.

Section 01

Why teams migrate to Salesforce

The four shapes a Salesforce migration takes, and what makes the platform harder — or easier — than the category average.

Salesforce, Inc. was founded by former Oracle executive Marc Benioff in March 1999 and is headquartered in San Francisco, California 1. For fiscal year 2026 the company reported $41.5 billion in annual revenue, and Sales Cloud sits at the centre of a broader stack that includes Service Cloud, Marketing Cloud, Revenue Cloud, Tableau, Slack and the Agentforce AI layer 1.

The typical Sales Cloud customer is a mid-market or enterprise revenue team — usually 100 to 10,000+ users — that needs deep customisation through Apex code, Flow, Validation Rules and a Role Hierarchy / Sharing Rules access model. Compared with HubSpot or Pipedrive, Salesforce positions on configurability and ecosystem depth rather than time-to-value; compared with Microsoft Dynamics 365, it positions on the AppExchange marketplace and a wider partner network.

The shapes of migration that actually land on Salesforce fall into four patterns. First, legacy consolidation: spreadsheets, Act!, SugarCRM, on-prem Microsoft Dynamics, or a homegrown SQL database where the source schema is loose and the project is really a re-architecture. Second, competitor exits from HubSpot, Pipedrive, Zoho or Insightly when the customer outgrows the source tier or needs Apex-level customisation 1314.

Third, multi-org consolidation, where two or more Salesforce orgs from past M&A activity are merged into one — typically the hardest shape because both sides carry incompatible Record Types, Sharing Rules and Apex Triggers. Fourth, platform standardisation, where a parent enterprise standardises acquired business units onto a single Sales Cloud org.

What makes migrating *to* Salesforce harder than the category average is the automation that runs on insert. Validation Rules, Apex Triggers, Workflow Rules, Process Builder and Flow all evaluate every imported record, and a workflow that expects a 10-digit phone number breaks the moment legacy data shows up with a country code 22. Most migration teams disable automation during the load and re-enable it post-cutover.

What makes it easier than the average is the External ID field type — a first-class upsert mechanism on every object, capped at 25 external IDs per object, that lets you match records by a value from the source system rather than by Salesforce's 18-character Record ID 3. Combined with the platform's job-based async loader and the load order discipline that External IDs enforce, the platform rewards teams that plan their upsert keys before writing a single row.

Apex Triggers, Flows, Validation Rules and Reports do not import — they are rebuilt from documentation. Teams that scope for that work up front finish on time; teams that assume parity do not.

The destination has a richer automation layer than the source, and it fires on every imported row unless you actively quiet it.

Section 02

The Salesforce data model you need to map into

Standard Objects, Custom Objects, Record Types, relationships, and the External ID upsert mechanism — the destination schema decoded.

Salesforce platform Contacts Companies Deals Tickets Tasks Notes
Standard objects orbit the platform; every association can be many-to-many with optional labels.

Salesforce's data model is built around Standard Objects (Account, Contact, Lead, Opportunity, Case, Campaign and others), Custom Objects you define yourself, and a Relationship model that includes Lookups, Master-Detail relationships and Junction Objects for many-to-many cases.

Before you can map a field, you need to know which Standard Object the row belongs on, which Record Type applies inside that object, which required fields the page layout enforces, and which field you will use as the External ID for upsert. The table below summarises the objects you will touch in a Sales Cloud migration.

Object Stores Required on import Tier
Account Companies, households, or person accounts Name (or Last Name on Person Accounts) All editions
Contact Individual people associated with an Account Last Name, Account ID (unless Individual model) All editions
Lead Unconverted prospects before qualification Last Name, Company All editions
Opportunity Revenue deals in a sales stage pipeline Name, Stage, Close Date, Account ID All editions
Case Customer service / support tickets Status, Origin All editions (Service Cloud for full tooling)
Campaign / CampaignMember Marketing programs + member junction Campaign Name; Member needs Lead or Contact ID All editions
Product2 / Pricebook / PricebookEntry Sellable catalogue + price book entries Name, ProductCode; PricebookEntry needs Product + Pricebook All paid editions
OpportunityLineItem / Quote / QuoteLineItem Products on a deal and quote documents OpportunityId + PricebookEntryId; Quote needs OpportunityId All paid editions
Task / Event Activities — calls, emails, meetings, notes Subject; ActivityDate or StartDateTime All editions (Activity object is virtual) [16]
Custom Objects Customer-defined record types Defined per object; needs deployed schema before load Enterprise+ for unlimited; lower editions capped

Salesforce assigns an 18-character Record ID (the canonical primary key) to every record on insert. You cannot set Record IDs on import — they are system-generated. The migration pattern is to use External ID fields instead: up to 25 custom fields per object (auto-number, email, number or text type) that you flag as External ID and use as the upsert match key 3.

Mark the External ID as *Unique* and case-sensitive to prevent silent duplicate merges. The async loader references the External ID by name in the job payload; if the value exists, the row updates, if not it inserts.

Relationships come in three shapes. Lookup is a loose one-to-many — deleting the parent does not cascade. Master-Detail is a tightly-coupled one-to-many where the child inherits ownership and sharing from the master and is deleted with it. Junction Object is a custom object with two Master-Detail relationships used to model many-to-many — OpportunityContactRole is the standard example connecting Opportunities to Contacts. Custom field types determine validation and storage; the catalogue below covers what you can model.

Field type Limits Notes
Text / Text Area Text 255 chars; Long Text Area 131,072 chars; Rich Text Area 131,072 Long Text counts 2 bytes per Unicode character 21
Number / Currency / Percent 18 digits total; up to 18 decimal places Currency respects multi-currency org settings
Date / Date-Time Date-Time stored in UTC; ISO-8601 on loader Wrong format silently imports as null on Data Import Wizard
Picklist (single / multi-select) 1,000 active values; 2,000 inactive on single-select Restrict picklist enforces strict ENUM — typo = rejection
Formula / Roll-Up Summary Formula 3,900 char compiled; Roll-Up needs Master-Detail Does not import — recomputed by platform after load
Lookup / Master-Detail 40 lookups per object; 2 Master-Detail max per object Master-Detail cascades delete; Lookup does not
External ID fields Up to 25 per object (auto-number, email, number, text) Primary upsert mechanism via loader and Data Import Wizard 3
Custom fields per object 500 on Enterprise; 800 on Unlimited Hard cap; Big Objects + External Objects for overflow

Record Types add a second axis: one Custom Object can have multiple Record Types, each with its own Page Layout, picklist value subset, and required-fields list. A Lead inserted with the wrong Record Type silently displays the wrong fields to the rep on day one — and the value RecordTypeId on every imported row decides which one it lands on.

Custom Objects participate in relationships exactly like Standard Objects, with the same Master-Detail cascade and Junction Object patterns. Big Objects (the platform's archive tier) default to 1 million records — you contact your Account Executive to raise that ceiling, and they are not used for active migration loads 11.

Section 03

Pre-migration prep — the work before you touch Salesforce

What must be true on the source, the destination, and across the team before the first row is loaded.

The single best predictor of a clean Sales Cloud migration is how much work you do on the source side before the first load job is submitted. Practitioners consistently report that field-mismatch breakage is not really about the fields — it is about the Validation Rules, Apex Triggers and Flows that fire on every imported row and reject anything the legacy data does not perfectly match 22.

Disable Validation Rules and Triggers during the load, then re-enable and run regression tests. Most migration teams skip the regression step — and pay for it on day five.

Treat the source export as raw material shaped to Salesforce's expected formats — email validated, phone normalised to international format, picklist values converted to the destination's exact case-sensitive values, dates rewritten to ISO-8601, owner emails resolved to Salesforce User IDs.

Source-side prep

  • Audit and dedup the source before export — Cloudingo, DemandTools and Plauti Duplicate Check are the Salesforce-native dedup tools most teams reach for, and they catch fuzzy-match duplicates that Salesforce's built-in Matching Rule and Duplicate Rule will silently merge during insert 25.
  • Stamp a stable External ID on every record in the source export — the legacy primary key, a UUID, or a composite key — and create a custom field on each destination object marked *External ID* + *Unique* + case-sensitive to land it 3.
  • Convert picklist values to the exact destination case — Salesforce restricted picklists enforce strict ENUM matching and reject any typo, casing difference or trailing space with bad value for restricted picklist field. Build a transform table per picklist.
  • Resolve owners by exporting your destination Salesforce User list (User.Id, Username, FederationIdentifier) and joining it to the source owner column. Rows whose OwnerId cannot be resolved fall to the integration user, which silently breaks owner-based Sharing Rules.
  • Decide what is in scope for historical activities. Tasks and Events can be inserted with backdated ActivityDate, but they archive automatically after 365 days and the IsArchived flag is not updatable directly 16.

Destination-side prep

  • Create a Full Sandbox (or Partial Copy on lower editions) from Setup → Sandboxes — a Full Sandbox copies production data and metadata for end-to-end dry-runs and the refresh interval is 29 days 17.
  • Provision users first, ideally through your identity provider (Okta or Microsoft Entra ID), and assign Permission Sets and Profiles before the load — Apex Triggers reference running user context and ownership assignment silently falls to the integration user if a referenced User does not yet exist.
  • Deploy every custom field, Record Type, Page Layout and picklist value to production via a deployment tool before importing — fields created in the destination after a row arrives cannot be back-populated cleanly.
  • Disable Validation Rules, Workflow Rules, Process Builder Flows and Apex Triggers that should not fire on bulk insert (or wrap them in an Trigger.New0.Bypass__c = true skip flag pattern). Re-enable post-cutover with a regression test plan 22.
  • Pre-create Pricebooks, PricebookEntries and Products before any OpportunityLineItem load — a Line Item targeting a missing PricebookEntry fails with INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST and the row is rejected.

People prep

Cutover works only when humans cooperate. Lock down a source-system freeze window — typically 24 to 72 hours — and communicate it to every department touching the CRM. Train sales reps on Sales Cloud daily workflows, Opportunity stage management and List Views before go-live, not after. A clean legacy-CRM migration of under 25,000 records often lands in a week; a multi-org consolidation with Apex rebuild and Pricebook reconciliation runs four to twelve weeks.

Section 04

Import mechanisms: Data Import Wizard and Data Loader

Multiple mechanisms in, each with different limits, object support, and async behaviour. Picking the wrong one stalls mid-migration at scale.

Salesforce exposes multiple load paths and the right one depends on dataset size, object mix, and whether you need to re-run idempotently. Data Import Wizard covers small, simple loads on a handful of objects. Data Loader and Workbench cover the medium tier. For programmatic, repeatable and very large loads, Data Loader's async mode (or a third-party iPaaS) takes over. Third-party tools sit on top of all of them.

Data Import Wizard

The native UI tool lives at Setup → Data Import Wizard and supports a deliberately limited set of objects: Leads, Accounts, Contacts, Campaign Members, Solutions, Person Accounts and Custom Objects. It does not support Opportunities, Cases or Products — for those you escalate to Data Loader. The record limit is 50,000 per import, file format must be CSV with UTF-8 encoding (not UTF-8 BOM, not ANSI), and dates must be in the org's locale format.

The Wizard's killer feature is built-in Duplicate Rule + Matching Rule enforcement on Accounts and Contacts — but that same feature silently blocks rows that should pass, so know to set the Allow Duplicates flag explicitly when the source rows are legitimately new 25. Use the Wizard for one-shot loads under 50,000 records on supported objects, or any time you want a visual mapping review.

Data Loader and Workbench

Data Loader is the desktop app (Windows/macOS) that ships from Salesforce. It supports every Standard and Custom Object, runs Insert / Update / Upsert / Delete / Hard Delete / Export operations, and supports both interactive and CLI modes for scheduled jobs. Workbench is the browser equivalent — useful for one-off jobs without local install.

Large-volume async loading

For programmatic, repeatable and very large loads, Data Loader can be configured to use the platform's async load mode. The job model is: create an ingest job with operation (insert/update/upsert/delete) and object, upload CSV data, then mark the upload complete to enqueue. Salesforce auto-chunks server-side — you do not size batches yourself.

Per-transaction limits compound on top: 100 SOQL queries and 150 DML statements per transaction — relevant because Apex Triggers firing on your import consume those quotas. Bulk operations also share a daily submission cap, so naive code that submits tiny batches will exhaust the daily allocation 27.

Third-party staging tools

Dataloader.io (web Data Loader from MuleSoft), Skyvia, Talend, Informatica Cloud, Jitterbit, MuleSoft Anypoint and ETL platforms like Fivetran, Airbyte and Stitch all handle Salesforce loads. For one-time migrations the value is repeatability under failure and built-in schema mapping; for ongoing syncs they become the system of integration. Most enterprise migrations end up on MuleSoft or Informatica when the source database is on-prem and the company already has an iPaaS licence.

Rule

Under 50,000 records on Leads/Accounts/Contacts/Custom Objects → Data Import Wizard. 50k–5 M records on any object → Data Loader. Over 5 M records, any repeatable / scheduled load, or complex Apex-heavy Custom Objects → Data Loader in async mode or an iPaaS layer.

Section 05

Mapping your data into Salesforce

The longest section — because field mapping plus Record Type plus External ID is where almost every Salesforce migration that fails actually breaks.

SOURCE SALESFORCE SALES CLOUD FirstName, LastName firstname, lastname AccountName company AnnualRevenue annualrevenue Owner.Email hubspot_owner_id CreatedDate createdate
Field-mapping flow — every source field resolves to a destination property or an explicit drop.

Mapping is where every Salesforce migration earns its scars. The schema decisions you make in your mapping spreadsheet determine whether Reports work on day two, whether Validation Rules accept user edits on day five, and whether your sales team trusts the data on day thirty.

Work object by object, top to bottom of the load order: Users first (already done in prep), then Accounts, then Contacts, then Leads, then Opportunities, then OpportunityLineItems, then Tasks/Events, then Custom Objects. Load order matters because every child row needs a parent External ID that already exists.

Account

Common source → Salesforce Account mapping

Source Destination
  • company_name
    Name

    Required (or LastName on Person Accounts)

  • legacy_account_id
    Legacy_Account_ID__c (External ID, Unique)

    Primary upsert key — create this custom field first 3

  • website / domain
    Website

    Used by Duplicate Rule fuzzy match — normalise format

  • industry
    Industry

    Restricted picklist — map to exact case-sensitive value

  • annual_revenue
    AnnualRevenue

    Currency; respect multi-currency org if enabled

  • parent account
    ParentId (Lookup)

    Set in a second pass after all Accounts load

  • owner
    OwnerId

    Resolve to Salesforce User Id; falls to integration user if missing

Contact

Common source → Salesforce Contact mapping

Source Destination
  • first_name / last_name
    FirstName / LastName

    LastName required

  • email
    Email

    Used by Standard Contact Matching Rule for dedup 25

  • phone
    Phone

    Normalise to international format before load 22

  • account_name
    AccountId (Lookup)

    Resolve via Account External ID upsert lookup, not by name

  • legacy_contact_id
    Legacy_Contact_ID__c (External ID, Unique)

    Primary upsert key for re-runs

  • owner
    OwnerId

    Map by Username or Salesforce User Id

Opportunity and pipeline stages

Recreate every Sales Process and every Opportunity stage in Salesforce before importing Opportunities. Each stage has a StageName value, a ForecastCategoryName, a numeric Probability and a Boolean IsClosed / IsWon. Stage history is preserved in OpportunityHistory, which is read-only — you cannot insert historical stage transitions directly. To preserve the timeline, populate custom datetime fields like Stage_Entered_Qualification__c from the source.

Opportunities that target a stage value not present in the assigned Record Type's Sales Process are rejected with bad value for restricted picklist field. Map source stages to destination stages explicitly per Record Type.

Common source → Salesforce Opportunity mapping

Source Destination
  • deal_name
    Name

    Required

  • stage
    StageName

    Restricted picklist by Sales Process per Record Type

  • amount
    Amount

    Currency; OpportunityLineItems override if used

  • close_date
    CloseDate

    Required; YYYY-MM-DD; cannot be null

  • account
    AccountId

    Resolve via Account External ID lookup

  • record_type
    RecordTypeId

    Drives Page Layout + Sales Process — set explicitly

  • owner
    OwnerId

    Drives forecasting + Role Hierarchy sharing

  • legacy_opp_id
    Legacy_Opp_ID__c (External ID, Unique)

    Upsert key for re-runs and reconciliation

Custom-field mapping strategy

Resist the urge to map every source custom field one-to-one. Enterprise Edition caps Custom Fields at 500 per object, Unlimited at 800. Migrate only fields used by an active Validation Rule, Apex class, Flow, Report or List View in the last 12 months. Excess fields waste field allocation, slow down Page Layouts and clutter Search results.

For picklist fields where source values do not match the destination, either: (1) extend the destination picklist with the missing values *before* loading, (2) collapse adjacent values during transform, or (3) introduce a parallel custom Text field that holds the legacy value verbatim. Formula and Roll-Up Summary fields do not import — Salesforce recomputes them on-platform — so any source formula must be rebuilt as a Salesforce formula field after schema deploy.

Historical activities — Tasks, Events, Notes, Emails

Salesforce models activities through the virtual Activity parent object and two concrete children: Task (calls, completed work, to-dos) and Event (meetings) 16. Both support backdated ActivityDate and a WhoId (Lead/Contact) and WhatId (Account/Opportunity/Case) lookup pair that places the activity on the related record's timeline.

Critical gotcha: Tasks and Events archive automatically after 365 days, moving to the ArchivedActivity shadow table — and the IsArchived flag is not updatable, so you cannot insert records pre-archived 16. Older historical activities sit in live storage until Salesforce's nightly archive job catches up, which means a 5-year activity backfill briefly counts against your full data storage allocation.

Files and attachments

Salesforce has two file frameworks: the legacy Attachment object (25 MB cap per file, no metadata customisation) and the modern Files framework built on ContentVersion + ContentDocument + ContentDocumentLink (10 GB cap per file in Lightning Experience, full metadata support). New migrations should always land on Files.

The migration pattern is: upload a binary as a ContentVersion with the file body as VersionData (base64) and Title, capture the returned ContentDocumentId, then link it to the parent record via a ContentDocumentLink row. For large attachment estates (TBs), most teams keep originals in S3 or Azure Blob and store a deep link in a custom URL field on the Salesforce record — only the most-recent or most-referenced subset inlines.

Audit trail, ownership and original timestamps

By default Salesforce stamps CreatedDate, CreatedById, LastModifiedDate and LastModifiedById on insert and they are read-only. To preserve original audit trail, you submit a one-time support case requesting Create Audit Fields permission, which then lets the loader set those four fields explicitly during insert.

Once enabled, you set CreatedDate and the others in your load payload. The permission applies org-wide and is usually toggled off after migration completes to prevent users from rewriting history. Field History Tracking (which captures per-field change history) supports 20 fields per object by default; Field Audit Trail (paid add-on) extends to 60 fields per object with 10-year retention.

CRM-specific: lead scoring, email/calendar sync, Apex/Flow rebuild

Lead scoring in Sales Cloud is delivered via Einstein Lead Scoring (predictive, AI-trained on your historical conversion data) or via custom scoring formulas. Neither imports from the source — Einstein needs at least 1,000 converted leads in the destination to start scoring, and custom scoring formulas are rebuilt from documentation. If you must preserve historical scores, land them in a Legacy_Lead_Score__c custom number field and let Einstein/your new formula accrue forward.

Apex Triggers, Flows, Process Builder Processes, Validation Rules, Workflow Rules, Approval Processes, Reports and Dashboards do not import — they are rebuilt against the new schema. Process Builder is being end-of-lifed; new automation should land on Flow 17. Scope the rebuild before signing the scope.

Email and Calendar sync (Gmail/Outlook via Einstein Activity Capture, or the older Lightning Sync) is configured per user under Setup → Einstein Activity Capture *after* users and OwnerIds are stable. Enabling it during the import window backfills duplicate emails against the contacts you are still loading.

Section 06

The pitfalls that derail Salesforce migrations

Specific failure modes — ranked by impact, each tied to the exact Salesforce mechanism that breaks.

High impact

Validation Rules and Apex Triggers firing on every imported row

Salesforce evaluates Validation Rules, Apex Triggers, Workflow Rules, Process Builder Processes and Flows on every insert and update by default. A workflow that expects a 10-digit phone number rejects every legacy row with a country code; a Validation Rule that requires a populated industry rejects everything that historically left it null 22. The mitigation is to disable Validation Rules and toggle Triggers behind a Bypass__c Custom Setting during the load, then re-enable and run a regression test plan before users log in 22. 22

High impact

Restricted picklist rejection on case-sensitive ENUM mismatch

Restricted picklists enforce strict ENUM matching against the picklist value set, and any typo, casing difference or trailing space returns bad value for restricted picklist field in Data Loader and partial-success on Data Import Wizard. The trap is that the same value may pass for one Record Type and fail for another because Record Types subset the active values. Build a transform table per object per Record Type, validate against the destination's exact value list, and run a 100-row dry-run before scaling.

High impact

CreatedDate locked unless Create Audit Fields is enabled

By default CreatedDate, CreatedById, LastModifiedDate and LastModifiedById are stamped to load day and are read-only. Teams discover this on day two when Reports filtered by Created Date return everything stamped to import day. The mitigation is to file a support case requesting the org-wide Create Audit Fields permission *before* the migration starts. Salesforce typically enables it for a defined migration window. Forgetting to disable it after cutover lets any privileged user rewrite history.

High impact

Standard Matching Rule silently merging legitimate non-duplicates

Salesforce's Standard Contact Matching Rule does fuzzy name + email matching by default, and the Account Matching Rule does fuzzy company-name matching. During a large import, two genuinely-distinct prospects with similar names get merged into a single record and the original Lead/Contact source row is lost 25. Set Allow Duplicates = true on loader jobs where source dedup has already run, or rewrite the Matching Rule criteria to require an exact-match field before scaling the load. 25

High impact

Silent partial-success on Triggers consuming governor limits

When Apex Triggers run on imported batches, each chunk shares 100 SOQL queries and 150 DML statements per transaction. A well-meaning Trigger that queries the parent Account for every Contact insert blows the SOQL limit on the 51st row of a 200-row chunk, and the loader returns a partial-success response — most rows insert, some fail, no obvious blocking error. Monitor logs for partial successes (not just failures) and re-import rejected rows by Legacy_ID after fixing the Trigger bulkification 22. 22

Medium impact

Custom field cap at 500 (Enterprise) / 800 (Unlimited)

Migrating every source custom field one-to-one burns the field allocation in months. Enterprise Edition caps Custom Fields at 500 per Standard or Custom Object, Unlimited at 800. Once you hit the cap, you cannot create new fields — you either pay to upgrade edition, delete dormant fields, or move overflow to a related Custom Object or to External Objects (Salesforce Connect). Audit field usage before migration: keep only fields referenced by an active Validation Rule, Apex class, Flow, Report or List View.

Medium impact

Daily submission ceilings throttle naive small-batch loaders

Async loader submissions share a daily ceiling per 24-hour rolling window 27. Naive code that submits 10-row batches blows through the daily allocation before lunch. Use the async loader for all new work, monitor remaining daily allowance, and parallelise within the platform envelope rather than queue depth. 27

Medium impact

Activity archive after 365 days, IsArchived not updatable

Tasks and Events older than 365 days move to the ArchivedActivity shadow table on Salesforce's nightly archive job, and the IsArchived flag is not updatable — you cannot insert records pre-archived 16. A 5-year activity backfill lands in live storage and counts against your full data storage allocation until the archive job catches up. Plan the storage spike or batch the activity backfill into yearly chunks separated by archive cycles. 16

Low impact

EU data residency requires Hyperforce region selection at org provisioning

Salesforce's Hyperforce architecture lets EU customers pin data to specific EU regions for GDPR residency compliance, but the region is set at org creation and changing it later requires a Salesforce-run migration project, not a customer setting toggle. If your migration target is an org already provisioned in the wrong region, schedule the region migration *before* the data migration, or you will move millions of rows twice. Hyperforce regions also have their own deployment pipeline considerations for sandbox refreshes.

Section 07

Validation and cutover

What to verify after the loader finishes, in what order — and how to fail safely when Triggers ate a chunk.

1 Read-only Source goes write-frozen 2 Final delta Export incremental changes 3 Import Load into Salesforce 4 Validate Reconcile + spot-check 5 Cut over Users on new system
Cutover sequencing — five gated phases between source read-only and full user access.

Validation is the bridge between the loader returning success and users being allowed in. Salesforce data-migration practitioners recommend a three-stage validation: a test load of 10 percent of records in a Full Sandbox with department-rep spot-checks, the full production load with real-time monitoring of partial-success counts, and a 30-day post-migration data-quality audit using DemandTools or Cloudingo to surface the merges the Matching Rule did silently34.

Build a reconciliation queries spreadsheet that compares source and Salesforce on each of the counts below. Anything outside a 0.5 percent variance gets investigated before login access opens.

  • Total Accounts inserted vs source, minus deliberately-excluded rows (test accounts, deactivated, role-based) — use SOQL SELECT COUNT() FROM Account WHERE Legacy_Account_ID__c != null to count only migrated rows.
  • Total Contacts per Account spot-check — pick 20 high-value Accounts and verify Contact counts match source, catches Matching Rule merges that collapsed two distinct prospects.
  • Total Opportunities per Stage per Record Type plus sum of Amount per Pipeline — a non-trivial dollar variance usually signals a stage-mapping error or a currency precision drop on multi-currency orgs.
  • Total Tasks + Events per ActivityDate bucket vs source — confirm backdated ActivityDate round-tripped and the rows did not archive prematurely.
  • OpportunityLineItem rollup: sum TotalPrice per Opportunity vs source line-item total — catches missing PricebookEntry references.
  • OwnerId distributionSELECT OwnerId, COUNT(Id) FROM Opportunity GROUP BY OwnerId and confirm no record landed on the integration user that should not have.
  • External ID uniquenessSELECT Legacy_Account_ID__c, COUNT(Id) FROM Account GROUP BY Legacy_Account_ID__c HAVING COUNT(Id) > 1 should return zero rows.

On top of reconciliation, run a manual spot-check protocol: pick 30 random records across objects and verify each field against the source UI. Pick five high-value Opportunities and trace the full graph — Account, Contacts, Line Items, Tasks, Quotes. If a non-trivial discrepancy shows up in three or more of the 30, halt the load, fix the root cause (almost always a Trigger or Validation Rule), and re-import the affected rows by Legacy_ID via Data Loader upsert.

Salesforce's native Recycle Bin holds deleted records for 15 days and can be used for small-scale undo from the UI 34. Undoing an Import under Setup is available only for Data Import Wizard imports launched within the last 24 hours and only deletes records the import created 34. For Data Loader there is no built-in undo — you delete by Legacy_Import_Batch_ID__c custom field and re-import from the cleaned source.

The rollback strategy practitioners actually use: full org backup via Salesforce Data Export (Setup → Data Export) or a third-party backup tool like Odaseva or OwnBackup *before* the migration starts, plus stamping every imported row with an Import_Batch_ID__c custom text field, so catastrophe means a SOQL delete by batch ID followed by re-import from clean source 34.

Cutover sequencing: (1) source goes read-only and team is notified; (2) final delta export captures everything that changed during the sandbox-test window; (3) delta upsert via Data Loader using Legacy_ID External IDs; (4) reconciliation queries run; (5) Validation Rules and Triggers re-enabled with regression test pass; (6) users get login access and a 48-hour hyper-care window; (7) source decommission scheduled 30 to 90 days out, never same day.

Section 08

Migration partners and tools

Summit and Crest Salesforce Partners, iPaaS vendors, specialist migration shops — what each is good for and how to choose.

The Salesforce Partner Program tiers consulting firms by Navigator certifications, Customer Satisfaction (CSAT) scores and Salesforce-credentialed engineer count. The named tiers are Global Strategic, Summit, Summit+, Crest and Ridge. 70 percent of Salesforce implementations are delivered through Partners rather than direct, and most non-trivial migrations end up with one.

Deloitte Digital, Accenture, Capgemini, IBM and Slalom dominate the global Strategic tier for enterprise multi-cloud rollouts. For mid-market Sales Cloud migration projects specifically, Summit-tier partners with explicit competitor-exit practices (Salesforce-from-HubSpot, Salesforce-from-Pipedrive, Salesforce-from-Microsoft Dynamics) tend to ship cleaner than generalist implementation shops. Salesforce also runs Professional Services in-house — typically the most expensive option but the one with deepest product-team access.

On the ETL and iPaaS side, MuleSoft (Salesforce-owned) is the default for enterprise integration with on-prem source systems, Informatica Cloud is common in regulated industries, and Fivetran, Airbyte, Stitch and Workato cover the warehouse-first stack. Their role in a migration is rarely the migration itself — it is the staging layer that lands source data, the transformation layer that converts picklist values and resolves OwnerIds, and the ongoing-sync layer that takes over once the one-time migration completes.

Dataloader.io and Skyvia sit in the lighter tier, useful for one-shot loader runs without writing code. Cloudingo and DemandTools handle the dedup-and-cleanse pass before insert.

Managed-migration cost ranges vary widely. A clean Pipedrive- or HubSpot-to-Salesforce move of under 25,000 records, standard objects only, no historical activities, typically lands in the $20,000–$60,000 range depending on data volume and the business-process re-mapping required. A multi-org consolidation with deal history, Custom Objects, OpportunityLineItem reconstruction and Apex/Flow rebuild runs $60,000–$500,000+, driven by record count, custom-field complexity, and integrations that need rebuilding 13.

For teams that want to outsource the migration end-to-end, FlitStack specialises in Salesforce migrations and handles the External ID schema design, async loader orchestration, Validation Rule and Trigger bypass setup, restricted-picklist transformation, historical-data preservation, and the reconciliation work described in Sections 5 and 7 of this guide. Pricing is fixed-fee, based on record count and source platform, with separate line items for Custom Objects, Apex/Flow rebuild scope and historical activity depth so the scope is transparent before signature.

This is one of several legitimate paths — the right choice for any given team depends on whether they want a Summit Partner with a wider services footprint, Salesforce Professional Services with deepest product-team access, an iPaaS-first approach via MuleSoft, or a specialist migration vendor focused on the load itself. Explore FlitStack →

Section 09

Frequently asked questions

The questions every Salesforce migration team works through before they sign the scope.

References

Sources

  1. 1 Salesforce — Wikipedia
  2. 3 Custom Field Attributes — Salesforce Help (External ID)
  3. 11 Increase Limit of Salesforce Big Object Storage Allocation — Salesforce Help
  4. 13 We ditched HubSpot at $2M revenue and saved $12K/year — r/CRMSoftware
  5. 14 Best Zoho CRM Alternatives for Custom Development — r/CRMSoftware
  6. 16 Uploading Activity data to Salesforce — Salesforce Stack Exchange
  7. 17 Sandboxes — Staging Environments for Customizing and Testing
  8. 21 Case Comment STRING_TOO_LONG — Salesforce Stack Exchange
  9. 22 Salesforce Data Migration: 7 Challenges and How to Solve Them — DEV
  10. 25 Salesforce Duplicate Management — Salesforce Stack Exchange
  11. 27 Async Load Limits — Salesforce Help
  12. 34 Undoing an Import — Salesforce Help

Need help running this migration?

FlitStack AI runs Salesforce Sales Cloud migrations end-to-end.

Fixed-fee pricing, a hands-on migration engineer, full field mapping and validation. The work described in this guide — done for you.