---
title: "How to Migrate from HubSpot CRM to Salesforce: Complete Guide"
slug: how-to-migrate-from-hubspot-crm-to-salesforce-complete-guide
date: 2026-07-17
author: Abdul
categories: [Migration Guide, HubSpot, Salesforce]
excerpt: "Step-by-step guide to migrating HubSpot CRM to Salesforce. Covers object mapping, API rate limits, the Lead/Contact split, and activity history preservation."
tldr: "Migrating HubSpot CRM to Salesforce takes 3 to 8 weeks. The biggest risk is the Contact-to-Lead/Contact split. Use API extraction, not CSV exports, to preserve engagement history."
canonical: https://clonepartner.com/blog/how-to-migrate-from-hubspot-crm-to-salesforce-complete-guide/
---

# How to Migrate from HubSpot CRM to Salesforce: Complete Guide


# How to Migrate from HubSpot CRM to Salesforce: Complete Guide

> [!NOTE]
> **TL;DR: HubSpot CRM to Salesforce Migration**
>
> Migrating from HubSpot CRM to Salesforce is a **medium-to-high complexity** data-architecture project, not a simple export-import. The realistic timeline is **3 to 6 weeks** for organizations under 100,000 records with standard objects, and **6 to 12 weeks** for enterprise datasets with custom objects, multi-pipeline deals, and full activity history. The single biggest risk is the **Contact-to-Lead/Contact split**: HubSpot uses one Contact object for everyone, while Salesforce enforces a strict Lead vs. Contact and Account separation. Getting that split wrong corrupts pipeline reporting from day one. HubSpot Engagements (emails, calls, notes, meetings) cannot be migrated 1:1 because Salesforce Activities use a polymorphic WhoId/WhatId model that accepts only one person and one related record per activity. HubSpot Workflows, Reports, and Dashboards cannot be exported — they must be rebuilt in Salesforce. Teams with fewer than 50,000 records and no custom objects can self-serve with CSV exports and Salesforce Data Loader. Anything above that, especially with engagement history and file attachments, benefits from a managed migration service or custom ETL pipeline.

## What Is a HubSpot CRM to Salesforce Migration?

A HubSpot CRM to Salesforce migration is the process of extracting Contacts, Companies, Deals, Products, Line Items, Engagements (emails, calls, notes, tasks, meetings), Pipelines, and Custom Objects from HubSpot and loading them into Salesforce as Leads, Contacts, Accounts, Opportunities, Product2/PricebookEntry, OpportunityLineItems, Tasks, Events, EmailMessages, Opportunity Stages, and Custom Objects.

The core architectural difference making this migration non-trivial is **object bifurcation**. HubSpot uses a single Contact object governed by Lifecycle Stages to track everyone from a cold subscriber to a paying customer. Salesforce enforces a strict separation between Leads, Contacts, and Accounts with an explicit conversion process. You cannot migrate a HubSpot Contact 1:1 — you must first decide whether it belongs in the Salesforce Lead bucket or the Contact bucket.

For a deeper architectural breakdown, see [Salesforce vs HubSpot Architecture: The CTO's Technical Guide](https://clonepartner.com/blog/blog/salesforce-vs-hubspot-architecture-the-ctos-technical-guide/).

## Why Do Enterprise Sales Teams Move from HubSpot to Salesforce?

The trigger is almost never "HubSpot is bad." <cite index="27-8,27-9,27-10">The trigger is usually "we just closed deal four and need group-level pipeline reporting by Friday" or "we are tracking cross-sell opportunities across three entities and nobody can agree which CRM holds the truth."</cite>

The concrete reasons teams migrate:

- **Multi-entity pipeline reporting.** <cite index="27-11,27-12,27-13">HubSpot works well for one company, one sales team, and one process. It starts to fray when you operate multiple business units with different sales motions, approval hierarchies, or reporting lines. Salesforce's architecture of Accounts, Contacts, Leads, Opportunities, and unlimited custom objects provides the layering and segmentation needed.</cite>
- **Advanced CPQ and revenue operations.** Salesforce Revenue Cloud (CPQ), multi-currency Pricebooks, and approval chains for complex quoting are not available in HubSpot.
- **Governance and compliance.** Salesforce offers field-level security, record-level sharing rules, Apex validation, and audit trails that HubSpot's permission model cannot replicate at enterprise scale.
- **Ecosystem depth.** Salesforce AppExchange has thousands of integrations for ERP, billing, contract management, and vertical-specific solutions that rely on the Salesforce data model.

Three architectural differences make the migration complex:

1. **Lead/Contact bifurcation.** HubSpot stores all people in a single Contact object with Lifecycle Stages. Salesforce enforces a strict Lead vs. Contact separation with an explicit conversion process that creates a Contact, an Account, and optionally an Opportunity.
2. **Activity architecture.** HubSpot Engagements can be associated with multiple Contacts, Companies, and Deals simultaneously through flexible many-to-many associations. <cite index="54-1,54-2,54-3">Salesforce Activities have a polymorphic relationship with other objects, meaning a Task or Event can relate to different types of records through the WhoId and WhatId fields.</cite> <cite index="53-8,53-9">WhoId relates to a Lead or Contact, while WhatId relates to an Account, Opportunity, Case, or custom object.</cite> Each Salesforce Activity gets exactly one WhoId and one WhatId.
3. **Product and pricing model.** HubSpot uses a flat Product library with Line Items on Deals. Salesforce separates pricing across Product2, PricebookEntry, and OpportunityLineItem, requiring a normalization step during migration.

## HubSpot to Salesforce Object and Field Mapping

The object mapping table below is the foundation of every HubSpot to Salesforce migration. Every decision downstream depends on getting this right.

| HubSpot Object | Salesforce Object | Notes / Caveats |
|---|---|---|
| Contact (Lifecycle Stage = Lead, Subscriber, MQL) | Lead | Split based on Lifecycle Stage or a custom qualification field. Requires a decision rule before migration. |
| Contact (Lifecycle Stage = SQL, Opportunity, Customer) | Contact + Account | Qualified contacts become Contacts linked to Accounts. Account must be created first. |
| Company | Account | Map HubSpot Company Domain to Salesforce Account Website. Company Owner maps to Account Owner. |
| Deal | Opportunity | Deal Amount maps to Opportunity Amount. Deal Stage maps to Opportunity StageName. Close Date maps to CloseDate. |
| Deal Pipeline | Opportunity Record Type + Stage picklist | Multiple HubSpot pipelines require separate Salesforce Record Types or a single Record Type with distinct Stage picklist values. |
| Product | Product2 + PricebookEntry | HubSpot Product Price maps to PricebookEntry UnitPrice. Standard Pricebook must exist. |
| Line Item | OpportunityLineItem | Requires valid OpportunityId and PricebookEntryId. |
| Owner | User | HubSpot Owner email must match Salesforce User email. Inactive users need handling. |
| Note | Task (or ContentNote) | Map to Task with Subject = "Note" or use Salesforce ContentNote for rich text. |
| Task | Task | HubSpot Task Due Date maps to ActivityDate. Task Owner maps to OwnerId. |
| Call | Task or Event | Map call duration and outcome. Use Task for logged calls, Event for scheduled calls. |
| Email | EmailMessage or Task | Requires Enhanced Email enabled in Salesforce (available in Enterprise Edition and above). Email body maps to TextBody or HtmlBody. |
| Meeting | Event | Map start/end times, attendees, and outcome. |
| Ticket | Case | Only relevant if migrating service data alongside CRM. |
| Custom Object | Custom Object | Must be created in Salesforce first. Field-level mapping required. |

### Field-Level Mapping Considerations

**Data type mismatches.** HubSpot stores most fields as strings internally, even numbers and dates. Salesforce enforces strict field types. A HubSpot "number" property stored as "10,000.50" will fail Salesforce validation if the target field is a Currency type and the string includes a comma. Strip formatting before load.

**Picklist handling.** HubSpot dropdown properties allow free-text values even when a dropdown is defined. Salesforce picklist fields reject values not in the defined value set. Audit HubSpot property values against the Salesforce picklist before loading, or enable "unrestricted picklist" temporarily during load. HubSpot multi-select picklists store values as comma-separated strings — Salesforce multi-select picklists use semicolons and require exact string matches.

**Multi-currency.** If your HubSpot portal uses multiple currencies, each Deal record has a `deal_currency_code` property. Salesforce requires multi-currency to be enabled org-wide (a one-way, irreversible setting), and every Opportunity must reference a valid `CurrencyIsoCode`. Failing to set `CurrencyIsoCode` explicitly means the loading user's default currency gets applied silently, creating quiet reporting errors if your HubSpot amounts were in GBP and the loader defaults to USD.

**Required fields.** Salesforce objects have required fields that HubSpot may not enforce. Opportunity requires `StageName` and `CloseDate`. Any HubSpot Deal missing a close date will fail on insert unless you set a default.

**External ID fields.** Create Salesforce External ID fields (e.g., `HubSpot_Company_ID__c`) before the first dry run. These are the cleanest way to upsert and rebuild relationships. Salesforce limits you to 25 external ID fields per object.

**Association labels.** HubSpot association labels can be renamed, and HubSpot itself warns that integrations should key off `typeId`, not the human-readable label. Match associations by type identifier during extraction, not display name.

**Multi-company contacts.** A HubSpot Contact can associate with multiple Companies. Salesforce requires a primary `AccountId` on the Contact record. Map the primary HubSpot Company as the primary Account, and use the Salesforce Account Contact Relation object or enable Contacts to Multiple Accounts (available in Enterprise Edition and above) for the remainder.

### What Has No Clean Equivalent in Salesforce?

- **HubSpot Workflows** cannot be exported. Rebuild as Salesforce Flows.
- **HubSpot Reports and Dashboards** cannot be migrated. Rebuild in Salesforce.
- **HubSpot Form Submissions** have no native Salesforce equivalent. Store as custom object records or Campaign Responses.
- **HubSpot Marketing Email history** (sends, opens, clicks) does not map to any Salesforce standard object. Consider Salesforce Campaign Members or a custom object.
- **HubSpot Sequences** (sales outreach cadences) do not map to Salesforce natively. Requires Salesforce Engagement or a third-party tool like Outreach or Salesloft.
- **HubSpot Calculated and Rollup properties** do not migrate. Salesforce uses Formula Fields and Roll-Up Summary Fields, which must be created in Salesforce configuration, not loaded via data import.
- **Tiered product pricing.** HubSpot supports tiered pricing through serialized `hs_tier_ranges` and `hs_tier_prices` values. Standard Salesforce objects give you Product2, PricebookEntry, and OpportunityLineItem, but no direct 1:1 landing for tier JSON. You either flatten to a single unit price, expand tiers into custom schema, or move pricing logic into CPQ.

## How Do HubSpot and Salesforce API Limits Affect Migration Speed?

### HubSpot Extraction: API Endpoints and Rate Limits

HubSpot CRM data is extracted through the v3 REST API. There is no bulk export API equivalent to Salesforce's Bulk API. Every record must be read through paginated REST calls or batch endpoints.

**HubSpot API access by tier:** HubSpot Starter plans have limited private app API access. Full programmatic extraction using private apps with the rate limits described below requires HubSpot Professional or Enterprise. Teams on Starter or Free tiers are limited to CSV exports from the HubSpot UI, which cannot export engagement bodies, associations, or custom object data.

**Key endpoints for extraction:**

- `GET /crm/v3/objects/contacts` — list all contacts, paginated
- `POST /crm/v3/objects/contacts/batch/read` — batch read up to 100 per call
- `GET /crm/v3/objects/deals`, `GET /crm/v3/objects/companies`
- `GET /crm/v3/objects/calls`, `GET /crm/v3/objects/emails`, `GET /crm/v3/objects/notes`
- `GET /crm/v4/objects/{objectType}/{objectId}/associations/{toObjectType}` — associations

**Rate limits (post September 2024 increase):**

| Tier | Burst Limit | Daily Limit | Search API Limit |
|---|---|---|---|
| Professional (private app) | <cite index="1-5">190 requests per 10 seconds</cite> | <cite index="1-5">650,000 requests per day</cite> | <cite index="30-1">5 requests per second</cite> |
| Enterprise (private app) | <cite index="1-7">190 requests per 10 seconds</cite> | <cite index="1-6">1,000,000 requests per day</cite> | <cite index="30-1">5 requests per second</cite> |
| With API Limit Increase pack | 190 requests per 10 seconds | <cite index="1-8">Adds 1,000,000 requests per day to the standard limit</cite> | 5 requests per second |

<cite index="32-11,32-12,32-13">Batch endpoints count as one request. HubSpot's batch create/update endpoints let you process up to 100 records in a single API call.</cite> <cite index="76-8">A batch read of 100 contacts costs 1 request, not 100.</cite> This is the primary optimization lever for extraction throughput.

<cite index="7-12,7-13,7-14">The CRM Search API is capped at a separate, stricter limit across all search endpoints.</cite> <cite index="7-23">The limit applies across ALL search endpoints combined.</cite> The Search API also caps at 200 results per page and 10,000 total results per query, making it a poor choice for full extraction. Use the list endpoints with cursor pagination for full exports and reserve Search for filtered delta extracts.

For association data, HubSpot's associations batch read allows up to 1,000 IDs per request body. Batch reads of object records do not return associations — you must fetch them in a separate pass.

**Throughput math.** At 190 requests per 10 seconds with batch reads of 100 records each, theoretical maximum extraction is roughly 114,000 records per minute. In practice, accounting for associations, pagination overhead, and backoff, expect 40,000 to 60,000 records per hour for contacts with full property sets and association data.

**Archived and deleted records.** HubSpot soft-deletes records to a recycle bin (recoverable for up to 90 days). Decide before extraction whether to include archived records. The `GET /crm/v3/objects/{objectType}?archived=true` parameter retrieves them, but they will appear in Salesforce as active records unless you flag them with a custom field or exclude them entirely. Most teams exclude archived records to avoid polluting the new CRM.

For detailed HubSpot export methods, see [How to Export Data from HubSpot Service Hub: Methods & API Limits](https://clonepartner.com/blog/blog/how-to-export-data-from-hubspot-service-hub-methods-api-limits/).

### Salesforce Load: Bulk API 2.0 Limits

<cite index="60-3,60-4">You can submit up to 15,000 batches per rolling 24-hour period. This allocation is shared between Bulk API and Bulk API 2.0.</cite>

<cite index="61-14,61-15">You can process up to 100 million records per 24-hour period using Bulk API 2.0.</cite>

| Salesforce Bulk API 2.0 Limit | Value |
|---|---|
| Batches per 24 hours | <cite index="15-1">15,000</cite> (shared with Bulk API 1.0) |
| Records per 24 hours | <cite index="61-1">100 million</cite> |
| Internal batch size | <cite index="61-21">10,000 records</cite> |
| Concurrent jobs | <cite index="61-25">25</cite> (Bulk API 2.0 + 1.0 combined) |
| Data per job | <cite index="61-18">150 MB</cite> (CSV format) |

**Salesforce Edition requirements for Bulk API 2.0:** Bulk API 2.0 is available in Enterprise, Performance, Unlimited, and Developer editions. Professional Edition does not include Bulk API access by default — it requires the "API Access" add-on. If your target Salesforce org is Professional Edition, confirm API access before planning your migration approach.

**Salesforce Governor Limits during bulk load:** Beyond Bulk API limits, Apex triggers firing during data load are subject to Salesforce governor limits: 100 SOQL queries per transaction, 150 DML statements per transaction, and 10-second CPU time limit per transaction. Complex triggers on Account or Contact can cause batch failures during migration. This is the most common cause of "partial success" results in Bulk API jobs during production migration.

**Salesforce data and file storage limits.** Salesforce allocates data storage per edition and user count. Enterprise Edition provides 10 GB base + 20 MB per user. Each record consumes approximately 2 KB. Migrating 500,000 activity records consumes roughly 1 GB of data storage. File storage is separate: 10 GB base + 2 GB per user license in Enterprise Edition. If you are migrating file attachments from HubSpot, calculate total file size before loading — exceeding storage limits blocks all inserts org-wide, not just file uploads.

For smaller reference-data loads (Users, Products, PricebookEntries), Salesforce sObject Collections can write up to 200 records in a single REST request — faster than spinning up a Bulk API job for small datasets.

For most HubSpot-to-Salesforce migrations, the Salesforce side is not the bottleneck. The real constraint is HubSpot extraction speed. That said, Bulk API 2.0 provides no completion SLA — actual throughput depends on server load, trigger complexity, and lock contention. Disable non-essential Apex triggers, validation rules, and Flows during bulk load to maximize throughput.

## Migration Approaches: Which Method Fits?

### 1. CSV Export + Salesforce Data Loader

Export HubSpot data as CSV files (from the HubSpot UI or API), transform in a spreadsheet or script, then import using Salesforce Data Loader.

- **When to use:** Small datasets under 50,000 records with standard objects only.
- **Pros:** Free, no API development needed.
- **Cons:** Cannot export engagement bodies (emails, call recordings) via HubSpot UI export. Loses all association data. Manual relationship re-linking required via VLOOKUP. No error handling or automation.
- **Risk:** High for anything beyond contacts and companies. Relationships break silently.

### 2. Native HubSpot-Salesforce Integration

HubSpot's official Salesforce integration syncs contacts, companies, deals, tickets, activities, and some custom objects between the two platforms.

- **When to use:** Parallel-run coexistence and delta sync during cutover — not historical migration.
- **Pros:** Built-in, no custom code. Supports ongoing bidirectional sync.
- **Cons:** Not a full backfill tool. HubSpot's own docs note that sales emails, tasks, meetings, notes, and sales content views only sync after the contact has been triggered to sync. Marketing email events sync only within 30 days. Form submissions sync only within one year. Limited control over transformation logic.
- **Risk:** Medium. Teams that assume this is a migration tool discover backfill gaps during UAT.

### 3. iPaaS / Integration Platform (e.g., Workato, MuleSoft, Integrate.io)

Low-code integration platforms with pre-built HubSpot and Salesforce connectors.

- **When to use:** Mid-market teams that want visual mapping and ongoing sync.
- **Pros:** Pre-built connectors reduce development time. Visual transformation layer. Supports continuous sync.
- **Cons:** Licensing cost ($500 to $3,000+/month). Limited control over edge cases. Most pre-built HubSpot connectors do not support engagement body extraction (email HTML, call recording URLs) or HubSpot v4 association types — verify connector capabilities against your specific data scope before committing. Rate limit handling varies by platform.
- **Risk:** Medium. Connector limitations surface during testing, not during planning.

### 4. Custom API ETL

Build extraction scripts against HubSpot's v3 API, transform in a staging layer, and load into Salesforce via Bulk API 2.0.

- **When to use:** Enterprise migrations with custom objects, complex field transformations, or full engagement history.
- **Pros:** Full control. Can preserve all associations and engagement bodies. Supports incremental sync.
- **Cons:** Requires engineering resources. Typical build time: 2 to 4 weeks of engineering effort. Must handle rate limiting, pagination, error handling, and retry logic.
- **Recommended libraries:** Python: `hubspot-api-client` (official HubSpot SDK) + `simple-salesforce` (Salesforce REST/Bulk API wrapper). Node.js: `@hubspot/api-client` npm package + `jsforce`. Both HubSpot and Salesforce provide official SDKs that handle authentication, pagination, and rate-limit retry.
- **Risk:** Medium if properly tested. Low with experienced engineers.

### 5. Managed Migration Service

A specialist team handles extraction, transformation, loading, validation, and cutover.

- **When to use:** Complex migrations with engagement history, custom objects, multiple pipelines, or tight timelines. Also when internal engineering bandwidth is already committed elsewhere.
- **Pros:** Lowest risk. Handles edge cases (polymorphic associations, multi-deal engagements, file attachments). Includes validation and rollback planning. Fastest time to go-live.
- **Cons:** Cost ($5,000 to $50,000+ depending on volume and complexity).
- **Risk:** Low.

### Comparison Table

| Criteria | CSV + Data Loader | Native Integration | iPaaS | Custom ETL | Managed Service |
|---|---|---|---|---|---|
| Best for | < 50K records | Parallel-run sync | Mid-market, ongoing sync | Enterprise, full control | Complex, tight timeline |
| Engagement history | No | Partial (backfill limits) | Partial | Yes | Yes |
| Custom objects | Manual | Limited | Limited | Yes | Yes |
| Engineering effort | Low | None | 1-2 weeks config | 2-4 weeks build | None |
| Typical cost | Free | HubSpot license | $500-3,000/mo | Engineering salary | $5,000-50,000+ |
| Risk level | High | Medium | Medium | Medium | Low |

## What Is the Correct Order of Operations?

The load sequence determines whether relationships survive intact. Loading records out of order creates orphaned references and broken lookups.

> [!WARNING]
> **Order matters.** If you load Opportunities before Accounts, every Opportunity fails because AccountId is required. If you load Activities before Contacts, WhoId resolution fails. There are no shortcuts.

**Step 1: Users/Owners.** Map HubSpot Owners to Salesforce Users by email. Deactivated HubSpot owners need a decision: reassign to an active Salesforce user or create the user as inactive. Store the HubSpot Owner ID → Salesforce User ID mapping.

**Step 2: Accounts.** Load HubSpot Companies as Salesforce Accounts. Store the HubSpot Company ID in a custom External ID field (`HubSpot_Company_ID__c`) on the Account object. This external ID is the backbone for all subsequent relationship linking.

**Step 3: Contacts and Leads.** Split HubSpot Contacts into Salesforce Leads and Contacts based on your qualification rules. Contacts must be linked to Accounts using the External ID from Step 2. Leads are standalone records.

**Step 4: Opportunities.** Load HubSpot Deals as Salesforce Opportunities. Link each Opportunity to its Account using the external ID. Map Deal Stage to a valid Salesforce StageName. Set CloseDate (required). If you use Products, set the `Pricebook2Id` on each Opportunity before loading line items.

**Step 5: Products and Line Items.** Create Product2 records, then PricebookEntries linked to the Standard Pricebook, then OpportunityLineItems linked to both the Opportunity and the PricebookEntry. This three-step chain breaks if you skip the PricebookEntry.

**Step 6: Activities (Engagements).** Load Notes, Tasks, Calls, Emails, and Meetings last, after all parent records exist. Each activity needs:

- **WhoId**: the Salesforce Contact or Lead ID (resolved from the HubSpot association)
- **WhatId**: the Salesforce Account, Opportunity, or Case ID (resolved from the HubSpot association)

This is where polymorphic mapping hits hardest. A HubSpot email associated with 3 Contacts and 2 Deals must be split into multiple Salesforce Tasks or EmailMessages, each with a single WhoId and WhatId.

For dense activity history, use serial loading. Salesforce task inserts can lock related Who, What, and Account records. If you load activities in parallel for high-activity accounts, lock contention becomes the slowest part of the cutover.

**Step 7: Files.** HubSpot file attachments on Engagements provide a signed URL that expires. You must programmatically download the binary file from HubSpot, upload it to the Salesforce `ContentVersion` object, and generate a `ContentDocumentLink` to attach it to the correct record. Files do not ride along with task inserts — they require their own load path. Calculate total file size before loading and verify against your Salesforce file storage allocation.

**Step 8: Associations, Junction Records, and Validation.** Create OpportunityContactRoles and any remaining many-to-many relationships using Salesforce junction objects or Shared Activities. Run record-count reconciliation, field-level spot checks, and relationship integrity tests.

Example API call for extracting HubSpot Contacts with associations:

```bash
GET https://api.hubapi.com/crm/v3/objects/contacts?limit=100&associations=companies,deals&properties=firstname,lastname,email,lifecyclestage,hs_lead_status&after={cursor}
Authorization: Bearer {access_token}
```

Example Salesforce Bulk API 2.0 job creation for Account upsert:

```bash
POST https://yourinstance.salesforce.com/services/data/v60.0/jobs/ingest
Content-Type: application/json
Authorization: Bearer {access_token}

{
  "object": "Account",
  "operation": "upsert",
  "externalIdFieldName": "HubSpot_Company_ID__c",
  "contentType": "CSV",
  "lineEnding": "LF"
}
```

Simplified load orchestration (Python with `simple-salesforce` and `hubspot-api-client`):

```python
from hubspot import HubSpot
from simple_salesforce import Salesforce

# Initialize clients
hs = HubSpot(access_token="hs_token")
sf = Salesforce(username="user", password="pass", security_token="token")

for batch in load_plan:
    transformed = map_and_validate(batch)
    result = sf.bulk.Account.upsert(transformed, "HubSpot_Company_ID__c")
    retry_transient_failures(result)
    quarantine_schema_errors(result)
    refresh_crosswalks(result)
```

## How Long Does a HubSpot CRM to Salesforce Migration Take?

A typical migration takes **3 to 8 weeks** from kickoff to go-live. The timeline depends on record volume, object complexity, and whether engagement history is in scope.

| Phase | Duration | Activities |
|---|---|---|
| Discovery and audit | 1-2 weeks | Inventory HubSpot objects, define scope, create field mapping document, establish Lead/Contact split rules |
| Salesforce configuration | 1-2 weeks | Create custom fields, custom objects, Record Types, picklists, validation rules, page layouts. Set up in sandbox first. |
| Build and test ETL | 1-2 weeks | Build extraction scripts, transformation logic, load processes. Run test loads in sandbox. |
| Pilot migration | 3-5 days | Migrate a representative subset to sandbox (see selection guidance below). Validate with stakeholders. Fix mapping issues. |
| Production migration | 1-3 days | Full data load to production during a low-activity window. |
| Validation and UAT | 3-5 days | Record-count reconciliation, field-level checks, user acceptance testing, pipeline reporting verification. |
| Post-go-live support | 1-2 weeks | Monitor for data issues, run delta sync for records created during migration window, user training. |

**Pilot subset selection guidance.** A 10% random sample is insufficient. Select a representative subset that includes: (1) the 10 highest-activity Accounts (most associated Contacts, Deals, and Engagements), (2) Contacts at every Lifecycle Stage to validate the Lead/Contact split, (3) Deals from every pipeline and stage, (4) at least 5 Contacts with multi-company associations, (5) records with custom object relationships, and (6) records owned by both active and inactive users. This subset exposes edge cases that random sampling misses.

### Risk Register

| Risk | Likelihood | Mitigation |
|---|---|---|
| Lead/Contact split corrupts pipeline reporting | High | Define and test split rules in sandbox before production. Validate with sales leadership. |
| Engagement history loss | Medium | Use API extraction (not CSV export) for email bodies and call notes. |
| Broken Opportunity-to-Account relationships | Medium | Use External IDs on all parent objects. Validate relationship integrity after each load phase. |
| Salesforce validation rules reject records | High | Review all validation rules before migration. Temporarily deactivate non-essential rules during load. |
| HubSpot API rate limiting delays extraction | Medium | Use batch endpoints, implement exponential backoff, schedule extraction during off-peak hours. |
| PricebookEntry mismatch on line items | High | Load PricebookEntry before OpportunityLineItem and set Opportunity Pricebook2Id first. |
| History gaps from native sync assumptions | High | Treat the native HubSpot connector as a delta transport, not an archive backfill tool. |
| Salesforce governor limits cause batch failures | Medium | Disable non-essential Apex triggers during load. Monitor for SOQL 101 and CPU timeout errors. Reduce Bulk API batch size from 10,000 to 2,000 if triggers cannot be disabled. |
| Salesforce data storage exceeded | Low-Medium | Calculate expected storage consumption before migration. Each record ≈ 2 KB. 500,000 activities ≈ 1 GB. Compare against org allocation (Enterprise: 10 GB + 20 MB/user). |

### Phased vs. Big-Bang vs. Incremental

**Big-bang** works for organizations under 100,000 records with a defined cutover weekend. All data moves at once, and teams switch on Monday morning.

**Phased** suits enterprise migrations. Migrate Accounts and Contacts first, validate, then migrate Opportunities and Activities in subsequent phases. Reduces risk but extends the timeline.

**Incremental with parallel running** is the safest approach for active sales teams. Migrate historical data first, then run a delta sync that captures new and updated records in HubSpot until the team fully cuts over to Salesforce. This prevents pipeline disruption during active sales cycles. For more on this strategy, see [Why Running Two CRMs in Parallel Beats a Hard Cutover](https://clonepartner.com/blog/blog/why-running-two-crms-in-parallel-beats-a-hard-cutover/).

### Dependencies and Rollback

Your primary dependency is API access and system administrator permissions in both environments. Go-live criteria should include a 99.9% record count match and successful UAT sign-off.

Keep HubSpot CRM licenses active for at least 30 days post-go-live. This provides a safety net for data validation and allows a rollback if critical data issues surface.

**Rollback scope and limitations.** Rollback of data is straightforward using External IDs for bulk deletion. Rollback of Salesforce configuration changes (custom fields, Record Types, page layouts, Flows) is more complex — these must be manually reverted or restored from a sandbox snapshot. If users have already created new records in Salesforce post-go-live, those records must be migrated back to HubSpot or manually reconciled, which adds 1-2 weeks of effort. Define a rollback decision deadline (e.g., 5 business days post-go-live) beyond which rollback is no longer practical.

## What Happens to Sales Activity History During Migration?

Preserving activity history is the difference between a migration that sales reps accept and one they fight. When reps open a Contact in Salesforce and see zero history, trust in the new system collapses on day one.

**What transfers:** Email logs, call records, meeting notes, task history, and notes can all be migrated as Salesforce Tasks, Events, or EmailMessages. The content (subject, body, timestamps, duration) carries over. Original dates can be preserved by setting `ActivityDate` and `CreatedDate` — the latter requires enabling the "Set Audit Fields" permission in Salesforce (available in Enterprise Edition and above; must be enabled via Salesforce Support for some editions).

**What does not transfer cleanly:**

- **HubSpot Timeline events** (page views, form submissions, list memberships) have no standard Salesforce equivalent. These must go into a custom object or be discarded.
- **Multi-association engagements** must be flattened. A HubSpot email associated with 3 Contacts becomes either 3 separate Salesforce EmailMessages (one per Contact) or 1 EmailMessage with the primary Contact only. The decision depends on your reporting needs.
- **Email tracking data** (opens, clicks) does not carry over to Salesforce natively.
- **Native connector backfill limits.** HubSpot's official integration only syncs activity after a contact is triggered to sync. Marketing email events sync only within 30 days, and form submissions only within one year. Full historical preservation requires API extraction, not the native connector.

**Forecasting continuity.** Migrating Deals with their current stage and close dates preserves pipeline reporting. The key is mapping HubSpot Deal Stages to Salesforce Opportunity Stages with correct probability values so forecasting models remain accurate.

**Change management.** <cite index="22-10,22-11">A lack of training can be the downfall of any new process or system, so it is critical to book time with each team to walk through their piece of the CRM.</cite> Salesforce operates differently than HubSpot — reps must learn how to convert Leads into Contacts and Accounts rather than simply changing a Lifecycle Stage field. Plan daily office hours for the first two weeks post-go-live.

## Salesforce Edition Requirements for Migration Features

Not all Salesforce features referenced in this guide are available in every edition. Confirm your edition supports the required capabilities before planning your migration approach.

| Feature | Professional Edition | Enterprise Edition | Unlimited/Performance |
|---|---|---|---|
| Bulk API 2.0 | Requires API add-on | ✅ | ✅ |
| Enhanced Email (EmailMessage object) | ❌ | ✅ | ✅ |
| Contacts to Multiple Accounts | ❌ | ✅ | ✅ |
| Set Audit Fields (preserve CreatedDate) | ❌ | Via Support request | ✅ |
| Custom Objects | Up to 50 | Up to 200 | Up to 2,000 |
| Record Types | Limited | ✅ | ✅ |
| Field-Level Security | ❌ | ✅ | ✅ |
| Sharing Rules | ❌ | ✅ | ✅ |
| Sandbox (Full) | ❌ | ❌ (Partial only) | ✅ |

If migrating to Professional Edition, plan for these constraints: no Enhanced Email means email bodies must be stored as Task Description fields (255-character limit on Subject, 32,000 on Description). No Contacts to Multiple Accounts means secondary company relationships from HubSpot require a custom junction object. No Set Audit Fields means original timestamps cannot be preserved on CreatedDate.

## Edge Cases and Known Limitations

**Polymorphic engagements.** A single HubSpot email can be associated with five Contacts and three Deals simultaneously. Salesforce Tasks support one WhoId and one WhatId. You must write logic to either select the primary association or duplicate the Task record across multiple objects. <cite index="57-1,57-2">If WhoId points to a Lead, WhatId cannot reference an Account directly from that Lead because no Account relationship exists yet.</cite> Plan your Lead/Contact split with this constraint in mind.

**File attachments.** HubSpot file exports provide a signed URL that expires. You must programmatically download the binary file from HubSpot, upload it to the Salesforce `ContentVersion` object, and generate a `ContentDocumentLink`. This is a separate, bandwidth-intensive process with its own error handling requirements.

**Duplicate contacts.** HubSpot deduplicates by email address. Salesforce does not enforce email uniqueness on Contact or Lead by default. Enable Salesforce Duplicate Management rules before loading, or deduplicate in the staging layer.

**Multi-deal associations.** A single HubSpot Contact can be associated with multiple Deals. In Salesforce, a Contact links to multiple Opportunities through OpportunityContactRole — but this junction record must be created explicitly after both the Contact and Opportunity exist.

**Secondary company relationships.** HubSpot's multi-company associations disappear unless you enable Contacts to Multiple Accounts (Enterprise Edition+) or model the relationships through a custom junction object.

**Salesforce validation rules and triggers.** <cite index="51-18,51-19">Apex triggers and validation rules encode undocumented business logic. Teams consistently discover that active triggers encode business decisions nobody on the current team made and nobody fully understands.</cite> Deactivate non-essential triggers and validation rules during migration, then re-enable after validation.

**Custom objects with circular references.** If HubSpot Custom Objects reference each other (Object A → Object B and vice versa), load one side first with a placeholder, then update the back-references in a second pass.

**Tiered product pricing.** HubSpot supports tiered pricing through serialized `hs_tier_ranges` and `hs_tier_prices` JSON values. Standard Salesforce objects have no direct 1:1 landing for tiered pricing. Flatten to a single unit price, expand tiers into custom schema, or implement CPQ.

**Inactive owners.** If a HubSpot engagement is assigned to an inactive owner, the native sync will error. The same problem hits during migration if you load records assigned to inactive Salesforce Users. Define a fallback owner rule before extraction.

**Task lock contention.** Salesforce task inserts can lock related Who, What, and Account records. For accounts with dense activity history, use serial loading mode to reduce database contention and avoid timeout failures.

**Data residency and GDPR.** HubSpot allows data center selection (US or EU). Salesforce instance location is determined at org provisioning. If your HubSpot data is hosted in the EU and your Salesforce org is on a US instance (e.g., na-prefixed instances), the migration involves a cross-border data transfer. For EU-based organizations, verify that your Salesforce org is on an EU instance (eu-prefixed), or ensure you have appropriate Standard Contractual Clauses (SCCs) or other GDPR transfer mechanisms in place before extracting personal data from HubSpot and loading it into Salesforce.

## How Do You Validate a HubSpot to Salesforce Migration?

Validation is where migrations are won or lost. A migration that loads records without verifying them will be re-done. A migration can also have perfect record counts and still be unusable if opportunities, owners, or activities are attached to the wrong parents.

**Layer 1: Record-count reconciliation.** Compare source counts (HubSpot) against target counts (Salesforce) for every object type. Use HubSpot's list API for total counts and Salesforce SOQL `SELECT COUNT() FROM Account` queries. Any discrepancy greater than 0.1% needs investigation.

**Layer 2: Field-level spot checks.** Sample 50 to 100 records per object type and compare field values between HubSpot and Salesforce. Check for:

- Text field truncation (Salesforce Text fields default to 255 characters; Long Text Area supports up to 131,072 characters)
- Date fields for timezone shift errors (HubSpot stores timestamps in UTC milliseconds; Salesforce DateTime fields are UTC but display in the user's timezone)
- Currency fields for rounding differences
- Picklist fields for rejected values
- Owner assignment accuracy

**Layer 3: Relationship integrity.** Verify that:

- Every Contact has a valid AccountId (no orphans)
- Every Opportunity has a valid AccountId
- Every OpportunityLineItem has a valid OpportunityId and PricebookEntryId
- Activities have valid WhoId and/or WhatId references
- OpportunityContactRoles exist for multi-contact Deals

**Pipeline reporting.** Run the same pipeline report in both HubSpot and Salesforce and compare totals by stage. This is the validation that matters most to sales leadership.

**UAT with end users.** Have 3 to 5 sales reps spend one day working in the migrated Salesforce org. Ask them to find specific accounts, review activity history, and verify deal data. Their feedback catches issues that automated checks miss.

**Rollback procedure.** Before production migration, agree on a rollback plan. Using External IDs makes bulk deletion straightforward:

```sql
SELECT Id FROM Account WHERE HubSpot_Company_ID__c != null
```

For a complete validation framework, see [The Ultimate CRM Data Migration Checklist: A 10-Point Plan for a Zero-Loss Transition](https://clonepartner.com/blog/blog/the-ultimate-crm-data-migration-checklist-a-10-point-plan-for-a-zero-loss-transition/).

## Build In-House or Use a Managed Migration Service?

**Build in-house when:**

- Your dataset is under 50,000 total records across all objects
- You have no custom objects or engagement history to migrate
- You have engineering resources with both HubSpot API and Salesforce Bulk API experience
- Your timeline is flexible (6+ weeks)

**Use a managed service when:**

- Your dataset exceeds 100,000 records or includes custom objects
- You need full engagement history preserved (emails, calls, notes with bodies and timestamps)
- Your sales team cannot tolerate pipeline disruption or downtime
- You need the migration completed in under 4 weeks
- You have tried a DIY approach and hit broken relationships or data loss

The hidden cost of DIY is not the initial build — it is the re-migration. Teams that discover broken relationships, missing activity history, or corrupted pipeline data after go-live spend 2 to 3 times the original effort fixing the problems under pressure from sales leadership.

ClonePartner has completed over 1,500 data migrations, including complex CRM projects with polymorphic activity mapping, multi-pipeline deal structures, and custom object relationship preservation. For teams that need engagement history migrated with full fidelity and zero downtime, that track record matters.

> Need to migrate from HubSpot CRM to Salesforce without losing activity history or breaking pipeline reporting? Talk to our migration engineers.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently Asked Questions

### How much does a HubSpot to Salesforce migration cost?

<cite index="24-27,24-28">Costs typically range from $10,000 for simple migrations to $100,000+ for complex enterprise implementations.</cite> A managed data migration service for a mid-market CRM (50,000 to 500,000 records) typically runs $5,000 to $30,000 for the data migration component alone, excluding Salesforce implementation and configuration. Cost tracks complexity more than row count — the expensive variables are custom objects, activity history, product and price book design, and whether you need a zero-downtime parallel run.

### Can I migrate HubSpot timeline activity to Salesforce?

Yes, but not all of it. Emails, calls, notes, tasks, and meetings can be migrated as Salesforce Tasks, Events, or EmailMessages using the HubSpot v3 API. HubSpot Timeline Events like page views, form submissions, and list membership changes have no standard Salesforce equivalent and must be stored as custom object records or discarded. The native HubSpot-Salesforce integration documents backfill limits that make it insufficient for full historical preservation — use API extraction instead.

### What data cannot be migrated from HubSpot CRM to Salesforce?

HubSpot Workflows, Reports, Dashboards, and Sequences cannot be exported or migrated. They must be rebuilt in Salesforce as Flows, Reports, Dashboards, and Sales Cadences. Marketing Email templates and analytics (send/open/click data), Form Submissions, Calculated Properties, and tiered product pricing structures also have no direct Salesforce equivalent.

### How do you handle the HubSpot Contact to Salesforce Lead vs. Contact split?

Define a qualification rule based on HubSpot Lifecycle Stage or a custom property. Contacts with Lifecycle Stage values of "subscriber," "lead," or "marketing qualified lead" typically migrate as Salesforce Leads. Contacts with values of "sales qualified lead," "opportunity," or "customer" migrate as Salesforce Contacts linked to Accounts. Lock this routing rule before building anything, and test the split with your sales team before production migration.

### Can I keep HubSpot running alongside Salesforce after migration?

Yes, and many teams do. <cite index="22-1,22-5">If you are planning on keeping HubSpot as a marketing tool post-migration, install the Salesforce integration and set up the field mapping for the Contact and Company objects.</cite> HubSpot Marketing Hub syncs with Salesforce CRM using the native integration, allowing marketing to continue in HubSpot while sales works in Salesforce. Keep HubSpot CRM licenses active for at least 30 days post-migration for rollback safety, and treat the native connector as your delta sync layer during coexistence.

### What Salesforce edition do I need for a full migration?

Enterprise Edition or higher is recommended. Professional Edition lacks Bulk API access (without an add-on), Enhanced Email, Contacts to Multiple Accounts, Set Audit Fields, and field-level security — all of which are referenced in this guide. If you are on Professional Edition, expect workarounds for email history storage, multi-company relationships, and timestamp preservation. See the edition requirements table above for a full breakdown.

## Frequently asked questions

### How much does a HubSpot to Salesforce migration cost?

Costs typically range from $10,000 for simple migrations to $100,000+ for complex enterprise implementations. A managed data migration service for a mid-market CRM (50,000 to 500,000 records) typically runs $5,000 to $30,000 for the data migration component alone, excluding Salesforce implementation and configuration.

### Can I migrate HubSpot timeline activity to Salesforce?

Yes, but not all of it. Emails, calls, notes, tasks, and meetings can be migrated as Salesforce Tasks, Events, or EmailMessages using the HubSpot v3 API. Page views, form submissions, and list membership changes have no standard Salesforce equivalent. The native HubSpot-Salesforce integration has backfill limits that make it insufficient for full historical preservation.

### What data cannot be migrated from HubSpot CRM to Salesforce?

HubSpot Workflows, Reports, Dashboards, and Sequences cannot be exported or migrated. They must be rebuilt in Salesforce. Marketing email analytics, form submissions, calculated properties, and tiered product pricing structures also have no direct Salesforce equivalent.

### How do you handle the HubSpot Contact to Salesforce Lead vs. Contact split?

Define a qualification rule based on HubSpot Lifecycle Stage. Contacts with stages like subscriber or MQL migrate as Salesforce Leads. Those with stages like SQL, opportunity, or customer become Salesforce Contacts linked to Accounts. Lock the routing rule before building anything and test with sales before production load.

### Can I keep HubSpot running alongside Salesforce after migration?

Yes. HubSpot Marketing Hub can sync with Salesforce CRM using the native integration, allowing marketing to continue in HubSpot while sales works in Salesforce. Keep HubSpot CRM licenses active for at least 30 days post-migration for rollback safety.
