Case file 01 · CRM migration

Two CRMs went in.
One clean source of truth came out.

Protolabs (NYSE: PRLB), the on-demand manufacturer, ran sales across separate HubSpot and Salesforce instances. We moved the HubSpot side into Salesforce through a Snowflake staging layer, so every account was cleaned, deduplicated and verified before it landed.

HUBSPOTsourcecontacts · companiesdeals · activitiesSNOWFLAKE + DBTstaging layerstandardizededuplicatematchSALESFORCEdestination355,793 accountslinked + verified381 pulled asideHUBSPOTsourcecontacts · companiesdeals · activitiesSNOWFLAKE + DBTstaging layerstandardizededuplicatematchSALESFORCEdestination355,793 accountslinked + verified381 pulled aside
clean recordduplicate, merged in stagingcross-company link, reversed
By the numbers

Accounts and scoped leads, verified across the full population. No sampling.

355,793
accounts linked across both CRMs and verified
205,657
net-new accounts created clean in Salesforce
398,870
leads matched to exactly one migrated account
16,000+
duplicate accounts merged by domain
381
cross-company links caught and reversed
7.7M
historical activities modeled in Snowflake with dbt
The catch

The hidden merges that would have quietly broken the CRM.

Deduplicating by company domain folded more than 16,000 duplicate accounts into their surviving records. Most teams would call that done.

We audited every merge. The overwhelming majority were right. But 381 had joined two different companies that happened to share a domain: internet providers, email hosts, incubators and bad website data. Left alone, each of those accounts would have collected another company's activity history the moment the next load ran.

So we unlinked all 381, restored the fields the merge had overwritten from Salesforce's own field history, and verified the full population: 381 of 381, zero failures. Every change shipped with a rollback snapshot.

16,000+ merges audited381 reversed
How it ran

Ten weeks, from first audit to closeout package.

  1. 01

    Assess

    Apr 22

    Inventoried the HubSpot data and the Salesforce model it had to land in, then set the readiness bar for what would move and what would not.

  2. 02

    Stage

    Landed HubSpot in Snowflake and built dbt models to standardize, deduplicate and match records before anything touched the destination.

  3. 03

    Link

    Matched accounts across both systems and wrote the link onto every Salesforce record, verified across the full population: 355,793 accounts.

  4. 04

    Merge

    Jun 7

    Ran a domain-based deduplication across the commercial database, folding more than 16,000 duplicate accounts into their surviving record.

  5. 05

    Audit

    Jun 15

    Audited every one of those merges, caught 381 that had joined two different companies, and reversed each one with a rollback snapshot on file.

  6. 06

    Hand off

    Jun 30

    Scoped 398,870 leads to a single matched account each and delivered a turnkey package for the conversion and activity load to run sandbox first.

How we work

Irreversible steps wait for the owner.

The last steps were lead conversion and the activity load, each irreversible at the scale of hundreds of thousands of records. Rather than run them alone on the final day, we handed Protolabs' team a turnkey package built to run in a sandbox first, with every script, file and rollback path documented.

Speed matters on a migration. Being able to undo it matters more.

closeout/
  • ├─Closeout runbook
  • ├─Data dictionary and refresh runbook
  • ├─Scoped lead files, matched and tie-break sets
  • ├─Lead conversion batch job (Apex)
  • ├─Activity load and verification scripts
  • └─Rollback snapshot for every destructive change

Delivered with Kameron Kretschmar and the Protolabs CRM team. Contracted through Robert Half.

Bring us your stack

Thirty minutes with the engineer who would run your build. We walk your current stack and say what we would ship first. No deck.

Book a Working Session