Migrating to Salesforce: A Data Migration Guide
Migrating to Salesforce means mapping your data into its object model, rebuilding automation in Flow and Apex with governor limits in mind, and testing at real volume in a sandbox — not exporting records and hoping the logic follows.

Key takeaways
- Salesforce migrations succeed or fail on object-model mapping, not data volume — deciding how source records become Accounts, Contacts, Leads and Opportunities has to happen before a single record moves.
- Automation rebuilt without bulkification in mind is the single most common way a Salesforce migration that 'worked in testing' breaks under real production volume.
- Data migration and mapping run roughly 15% of a typical Salesforce implementation budget, while integration and custom development (Apex, API work) absorb the largest share at roughly 30% — customization, not the data move itself, is usually the bigger cost driver.
- Cited industry ranges put small-business Salesforce implementation at $5k-$12k, scaling to $15k-$40k mid-market and $40k-$150k+ for a multi-cloud enterprise build — seat count moves this far less than Apex development and cloud count.
- Sandbox testing at realistic data volume, with actual end users checking their own records and reports, catches the issues that a 200-record test migration never surfaces.
A typical Salesforce migration timeline by phase — proportional, not a fixed schedule. Data volume and automation complexity shift these percentages meaningfully.
Migrating to Salesforce is less about moving records and more about correctly mapping your data into Salesforce’s object model — standard objects, custom objects, and the relationships between them — and rebuilding your automation using Flow and Apex rather than copying logic that won’t translate directly. Teams that treat it as a pure data-export exercise usually end up with a system that holds the old data but doesn’t actually reflect the old process. If you haven’t fully committed to Salesforce yet, the HubSpot vs Salesforce comparison and the platform-agnostic CRM migration guide are worth reading first — this guide assumes Salesforce is the confirmed destination.
Map your data to Salesforce’s object model first
Salesforce structures data around standard objects (Account, Contact, Opportunity, Lead) plus any custom objects you build. Before migrating, decide how your source data maps onto this structure — a “Company” in your old system usually becomes an Account, but the mapping isn’t always that clean, especially for platforms with a flatter data model (a single “Contact” that combines what Salesforce splits into Lead and Contact, for example). Get this mapping documented and reviewed before any data moves, since restructuring relationships after records are loaded is far more painful than mapping correctly the first time.
In practice this means walking through every field in the source system and assigning it one of four outcomes: maps directly to a standard field, maps to a new custom field, gets combined with another field during transformation, or gets dropped because it no longer reflects the process. Teams that skip the “drop” category tend to recreate every field their old CRM accumulated over years, including the half-used ones nobody actually reports on — carrying forward clutter instead of leaving it behind. The mapping document should also flag picklist values that need normalizing (three spellings of “Enterprise” is a common find) before they become three different values in a Salesforce picklist.
Migrating from a flat CRM (HubSpot, Pipedrive) is a bigger structural project than migrating between two enterprise systems
Does moving from HubSpot or Pipedrive to Salesforce need different mapping work than an enterprise-to-enterprise migration? Yes, and it’s the part most migration quotes underscope. HubSpot and Pipedrive are both built around a single flexible object (a “deal” or a “contact” with custom properties layered on) rather than Salesforce’s relational model of separate Lead, Contact, Account and Opportunity objects tied together by lookup relationships. A HubSpot deal with a company name typed into a text field doesn’t automatically become a linked Salesforce Account; someone has to decide whether that text field becomes a new Account, gets matched against an existing one, or gets dropped in favor of a cleaner re-entry.
That extra structural step means the mapping document for a flat-CRM migration needs an explicit pass just for splitting combined data into the right target objects, on top of the field-by-field mapping every migration needs. Skipping this pass is exactly how teams end up with a Salesforce org full of Opportunities with no linked Account, which quietly breaks account-level reporting and territory assignment the day someone tries to run either. If HubSpot is specifically where you’re migrating from, the HubSpot migration guide and HubSpot to GoHighLevel migration guide cover source-side considerations that complement the Salesforce-side mapping work described here.
Plan record types and page layouts around real usage, not defaults
If different teams or products need different fields and processes, Salesforce’s record types and page layouts handle that — but only if planned before migration, not bolted on after. Decide up front whether you need multiple record types (e.g. separate Opportunity record types for new business versus renewals) rather than migrating everything into one generic layout and retrofitting structure later.
A useful test: if two teams selling different products would answer “what fields matter on this record” differently, that’s a signal for separate record types and page layouts rather than one shared layout with optional fields everyone scrolls past. Getting this wrong in the other direction — too many record types for processes that are actually identical — creates its own maintenance burden, since every record type needs its own page layout, validation rules and often its own sales-process picklist values to keep in sync.
What migrating to Salesforce typically costs, by company size
Salesforce’s implementation cost range is wide because “Salesforce” can mean a single-cloud, lightly customized rollout or a multi-cloud build with Apex development and a dozen integrations. The chart below shows the cited industry cost range by company size:
Notice the enterprise bar has by far the widest range ($40k to $150k+) — that spread is Apex development, multi-cloud scope (adding Service Cloud or CPQ on top of Sales Cloud) and integration count doing the work, not seat count. A 100-user org with a clean, single-cloud setup can land near the low end of the mid-market range, while a 20-user org running CPQ and three system integrations can land near the enterprise ceiling. Where your migration actually falls depends on scope, not headcount — which is exactly what a scoping call is for.
Rebuild automation with governor limits in mind
Workflow rules, email alerts and approval processes from another platform don’t transfer — they need to be rebuilt in Flow (and Apex where the logic requires it), and rebuilt correctly means respecting Salesforce’s governor limits from the start: bulkified triggers that handle batches of records, not one-at-a-time loops that hit API call limits under real production volume. This is the single most common place migrations that “worked in testing” break once real usage hits them.
Salesforce’s own Apex governor limits reference sets the specific ceilings that trip up rebuilt automation: 100 SOQL queries per synchronous transaction (200 in an async context), 150 DML statements per transaction, a 10-second CPU time limit, and a 6 MB heap size. A trigger written to query or update one record at a time can look identical in a code review to one that batches correctly — the difference only shows up when a bulk import, a mass reassignment, or a marketing sync pushes 500 records through the same trigger in one transaction and the per-transaction query count blows past 100. Rebuilding automation against these specific numbers, not just “make it work,” is what separates a migration that survives its first real bulk operation from one that doesn’t.
It’s worth being clear-eyed about where migration risk actually comes from before assuming Salesforce itself is the variable. Industry research into CRM implementation failure consistently finds technology accounts for a small share of the problem: one 2025 analysis of CRM project outcomes put the overall CRM implementation failure rate at 55%, with more than 60% of failures traced to people and process issues — poor user adoption, unclear ownership, weak change management — against roughly 10% attributable to the technology itself. Choosing Salesforce doesn’t create migration risk on its own; skipping the mapping, governor-limit, and adoption work in this guide does.
Before rebuilding a single automation, list every workflow, notification and approval step the old system runs and mark which ones actually still reflect how the team works today versus which ones accumulated as one-off exceptions nobody remembers the reason for. Rebuilding a legacy exception exactly as it existed is how a clean Salesforce org quietly inherits the same automation sprawl the old CRM had — this is the moment to prune, not just port. For anything that touches more than a handful of records at once (a nightly sync, a mass status update), design it as a batch or queueable Apex job from the outset rather than a synchronous trigger, since that’s the difference between a job that scales and one that starts throwing limit exceptions the day record volume doubles.
How much data can actually move at once, and how fast
Salesforce gives you three different tools for loading data, and picking the wrong one for your data volume is a common source of migration delay. The point-and-click Data Import Wizard, built into Setup, handles up to 50,000 records per object and is meant for genuinely simple loads with minimal transformation — fine for a short list of custom objects, not for a full CRM migration. Data Loader, Salesforce’s free desktop and CLI tool, can run against the standard SOAP API for smaller batches or against the Bulk API for real volume: Bulk API processes records asynchronously in batches (2,000 records per batch by default, configurable up to 10,000), which is what makes it practical to move hundreds of thousands of records without the load timing out or hitting per-transaction limits the way a synchronous load would.
The practical implication for planning a migration timeline: reference data (Accounts, then Contacts that depend on them) has to load before the records that reference it (Opportunities, Cases), because Salesforce’s relational model means a child record referencing an Account that doesn’t exist yet either fails or loads without the relationship intact. A migration plan that loads objects in dependency order, and validates row counts and a sample of relationships after each object loads rather than after the entire migration completes, catches a broken mapping in the object where it happened instead of three objects later when a report turns up empty relationships with no obvious cause.
What is a sandbox, and which type do you need to test in?
A Salesforce sandbox is a copy of your org used for testing that isolates the test from live production data, and which type you use changes how realistic that test actually is. A Developer sandbox gives a small amount of storage and no production data at all, useful for testing automation logic in isolation but not for catching volume-related issues. A Partial Copy sandbox pulls a defined sample of production data using a sandbox template you configure, giving a more realistic (if still partial) test. A Full sandbox copies the entire production org, including all data — the only sandbox type that reliably surfaces the issues (governor-limit breaches, report and dashboard behavior at real volume, sharing-rule edge cases) that a smaller test environment structurally can’t show you, per Salesforce’s own sandbox documentation.
Full sandboxes take longer to refresh (Salesforce enforces a minimum refresh interval, commonly cited around 29 days) and cost more than Developer or Partial Copy sandboxes, which is why many teams default to a smaller sandbox type to save time and then discover volume-related issues only after go-live. For a migration specifically, the tradeoff is worth making deliberately: a Full sandbox test costs more calendar time up front but is the only environment where “does this survive real production volume” gets a real answer before it’s your live org finding out.
Handle deduplication with Salesforce’s tools
Salesforce has built-in duplicate rules and matching rules that can catch new duplicates going forward, but they don’t retroactively clean data that’s already messy at import. Run de-duplication on the source data before migration (see the general CRM migration guide for the process), then configure Salesforce’s duplicate rules to prevent the same mess from recurring after go-live.
Matching rules typically compare on fuzzy criteria — company name similarity, email domain, phone number format — and it’s worth tuning these deliberately rather than accepting the defaults. A matching rule set too loosely flags legitimate separate accounts (two different companies that happen to share a common word in their name) as duplicates and trains users to ignore duplicate warnings entirely; one set too tightly lets real duplicates back in within weeks of go-live.
Decide, object by object, whether a duplicate rule should block the save entirely, warn but allow it, or just report on it after the fact. Blocking makes sense for Accounts and Contacts, where a duplicate genuinely causes downstream reporting problems. A warn-only rule is usually the better call for Leads early after go-live, since Lead volume from marketing sources tends to produce enough near-duplicates that a hard block would frustrate reps faster than it prevents real mess, and warn mode still gives you the data to tighten the rule once you see what it’s actually catching.
Which org-level settings have to be decided before migration, because they can’t be changed later?
A handful of Salesforce settings are effectively permanent once your org has live data in it, and getting caught by one after migration is far more expensive than deciding it up front. Person Accounts is the clearest example: it’s an org-wide feature that merges the Contact and Account model for B2C-style records (a single person who is also the account), and Salesforce does not offer a clean, supported way to turn it on for an org that already has standard Business Accounts with real data in production. If your business sells to individual consumers rather than companies — a med spa, a real estate brokerage working with buyers directly, a financial advisory practice — decide whether Person Accounts fits your model before the first record loads, because reversing that decision after go-live typically means a second, disruptive data migration rather than a settings change.
Currency works the same way at a smaller scale. A single-currency org can be converted to multi-currency, but the reverse isn’t true, and once multi-currency is enabled you’re committed to it as an org-wide setting even for teams that never touch international deals. Enabling multi-currency you don’t need adds a currency field and conversion-rate maintenance to every currency-aware object in the org for no benefit; not enabling it when you do need it means a migration project later, once the first international deal already needs updated exchange rates that don’t exist. State and Country picklists carry a similar one-way quality — Salesforce’s newer picklist-based state/country fields replace free-text entry, and switching an org that’s accumulated years of inconsistent free-text state and country data over to picklists after the fact means a cleanup project that’s much cheaper to do once, during migration, than to do twice.
None of these are hard to get right — Salesforce’s own Person Accounts documentation and multi-currency setup guides spell out exactly what each setting does. The risk isn’t complexity; it’s that these settings look like minor checkboxes in Setup and get skipped during the mapping and scoping conversation, then surface as a scope-changing problem three months after go-live when the business tries to do something the org-level setting quietly forecloses. Add a short “org settings that can’t change later” checklist to the mapping document specifically so someone signs off on Person Accounts, multi-currency, and state/country picklist format before the migration, not after.
Use a sandbox — not production — to test the real migration
Salesforce sandboxes exist specifically for this: run the full migration into a full or partial sandbox first, using real (anonymized where needed) data volume, and validate reports, dashboards and automation against it before touching production. A migration that looks clean with 200 test records can behave very differently at 50,000 real ones — sandbox testing at realistic volume is the only way to catch that before go-live.
Have actual end users — not just the admin who built the migration — check their own records, pipelines and reports in the sandbox before cutover. Admins tend to check that the data loaded correctly; sales reps notice when a deal’s stage history looks wrong or a report is missing a filter they rely on daily. Budget real calendar time for this round of user validation rather than treating it as a formality between “migration complete” and “go-live” — it’s usually where the last real issues surface before they become production problems.
Migrating from an industry-specific process
Salesforce’s flexibility matters most for teams whose sales process doesn’t fit a generic pipeline. A real estate brokerage migrating listing and transaction data, a financial services firm with compliance-driven approval chains, or a manufacturer with a long, quote-heavy cycle involving multiple products per deal will each need custom objects or record types that a generic Sales Cloud default doesn’t provide out of the box. The mapping work described above matters even more in these cases — a “Deal” in a real estate CRM might need to become an Opportunity linked to a custom Property object rather than a standard Opportunity alone, and getting that relationship right during migration is considerably cheaper than restructuring it after go-live once reports and dashboards are already built against the wrong shape.
Plan the cutover window deliberately
Pick a specific cutover date rather than “sometime after testing wraps up.” In the days before cutover, freeze significant changes to the source system or run a delta sync so the final migration captures everything created since the sandbox test. Communicate the freeze window clearly to the whole team, not just the admins — most post-migration complaints trace back to a record created or changed during an undocumented freeze window, not to the migration logic itself. After go-live, budget at least a week of close monitoring: spot-check migrated records against the source system, confirm automation fires correctly on real new records, and verify integrations are sending and receiving data before calling the migration complete.
Don’t forget files, attachments, and API rate limits during cutover
Records aren’t the only thing that needs to move. Attachments, notes, contracts, and email history sitting on records in the old system need their own migration path, and Salesforce treats file storage as a separate, metered resource from data storage — a detail that’s easy to miss until a migration plan built around record counts alone runs into a storage-limit warning mid-load. Decide early whether historical attachments migrate in full, migrate for a defined recent window only, or stay accessible in a read-only archive of the old system instead of moving at all; migrating years of accumulated file attachments in full is rarely worth the storage cost and load time it adds; most teams migrate current and recent files and leave older ones in an archived export.
The other easy-to-miss mechanic is API rate limits during the cutover window itself. Salesforce enforces a rolling 24-hour API call limit per org, based on edition and user count, and a migration that’s simultaneously running a bulk data load, a parallel integration sync, and manual testing by several team members can hit that ceiling faster than expected, especially on a smaller-edition org. Scheduling the bulk load for a low-traffic window, and pausing non-essential integrations during the load itself, avoids a scenario where the migration and a live integration compete for the same API budget on cutover day.
Where the rest of a Salesforce migration budget goes
Data migration is usually the largest variable within a Salesforce implementation budget — see the Salesforce implementation cost guide for cited industry ranges by company size and the specific cost drivers, including hidden costs like sandbox/environment licensing and AppExchange package fees that a simple license-price comparison misses. Industry cost-phase research also breaks down where the rest of a typical Salesforce budget goes: roughly 30% to integration and custom development (the largest single share), 20% to schema and object design, 20% to sandbox migration and testing, 15% to data audit and mapping, and 15% to UAT and training — a useful reference point when a vendor’s quote allocates the work very differently.
Get your migration scoped
A free 30-minute call reviews your current setup — whatever platform you’re on now — and gives you a written read on what a Salesforce migration for your specific data and process actually involves.