Map the object model before you touch an export
HubSpot and Salesforce look similar and behave differently. Salesforce lets a Contact exist without an Account; HubSpot associates records more loosely but drives automation off association labels. Get this wrong and every downstream report is wrong.
| Salesforce | HubSpot | What breaks if you skip it |
|---|---|---|
| Account | Company | Domain-based auto-association creates duplicate companies |
| Contact / Lead | Contact (with lifecycle stage) | Leads imported as a separate object nobody maintains |
| Opportunity | Deal | Stage probabilities and close-lost reasons lost |
| Case | Ticket | SLA history and pipeline stage timing disappear |
| Task / Event | Activity (call, meeting, task) | Timeline looks empty on day one and reps stop trusting it |
| Custom object | Custom object (Enterprise) or child records | Silent data loss if the edition doesn't support it |
Clean before you load, not after
Every hour spent de-duplicating in the staging file saves three in HubSpot. Once bad records are live and workflows have fired on them, unwinding means undoing emails, task assignments and lifecycle-stage history.
- De-duplicate on email for contacts and on root domain for companies — not on company name.
- Normalise picklists. 'Closed Won', 'closed-won' and 'Won' must become one value before import.
- Decide what happens to records with no owner and no activity in 24 months. Usually: import to a quarantine list, not the main database.
- Fix date formats and country codes at the file level. HubSpot will accept nonsense and report on it forever.
- Keep the Salesforce record ID in a custom property. It is your only reliable key for reconciliation and rollback.
Load in dependency order
Run a pilot with 200 records of each object before the full load. You will find at least one mapping error, and finding it at 200 records costs an afternoon rather than a weekend.
- 01Companies — the parent record everything else associates to.
- 02Contacts, associated to companies by domain or by the Salesforce Account ID you carried across.
- 03Deals, with pipeline and stage mapped, associated to both.
- 04Tickets, if you're moving Service Cloud.
- 05Activities and notes — the largest volume and the slowest step.
- 06Attachments and files, last, once associations are verified.
Reconciliation: the step that makes it defensible
A migration isn't done when the import finishes. It's done when you can hand the client a report showing source count, target count and variance for every object and every critical field, with an explanation for each variance.
We reconcile at field level rather than record level, because record counts hide the common failure: 68,000 deals imported, 12,000 of them missing close-lost reason. On our largest ticket migration we moved over 70,000 records with a full reconciliation report and 100% data integrity.
Cutover and the two weeks after
Freeze Salesforce writes on Friday, run the delta load, verify, and open HubSpot Monday morning with training already delivered. Keep Salesforce read-only for at least 60 days — it costs a little licence money and buys enormous confidence.
Plan hypercare. The first two weeks generate more support tickets than the whole build, and almost all of them are 'where did X go' rather than genuine faults.
What changed recently that affects migrations
HubSpot's pricing is seat-based, so licence planning during migration is now about who needs a paid Core Seat versus a free View-Only seat — a change that meaningfully reduces cost on large teams if you audit seat needs during the project rather than after.
Breeze AI features across the hubs lean heavily on clean, well-associated CRM data. AI summaries and prospecting agents inherit whatever mess you import, which raises the payoff for cleaning during migration rather than promising to do it later.
Common mistakes
- Importing activities before associations are verified, so half the timeline attaches to the wrong record.
- Dropping the Salesforce record ID — you lose your ability to reconcile or roll back.
- Migrating everything because 'it's already there', including 40,000 dead leads you then pay to store.
- Turning workflows on before the import finishes, so thousands of contacts get an onboarding email.
- Cancelling Salesforce on go-live day.
