Two weeks after the new CRM goes live, a sales manager opens a deal and notices the expected close date is empty. So is the next one. By the afternoon someone has worked out it is empty on roughly 900 records.
The old system stored it in a custom field with a name nobody recognised, and it was never mapped. The import tool reported success on every row, because from its point of view every row imported fine.
That is the shape of almost every CRM migration failure I have seen. Nothing crashes. The project gets declared finished. The damage surfaces later, in pieces, usually when someone needs the data for a forecast.
Decide what you are not migrating
Start here, because this single decision removes most of the work and most of the risk.
The default instinct is to bring everything. Everything means every field has to be mapped, every record has to be verified, and in some systems every contact carries a licence cost forever. It also means you rebuild your existing mess inside a system you are paying to fix it.
Leave behind:
- Contacts with no activity in two or more years and no open deal
- Deals closed lost more than two years ago
- Duplicates you have never merged
- Email addresses that bounce, along with anything on your suppression list that is already recorded elsewhere
- Custom fields nobody has filled in since 2023
A migration is the one moment when deleting data is easy and nobody argues. Six months later, deleting anything requires a meeting. Take the window.
Export what you drop to a CSV and put it in storage. Then nobody can block the decision by saying they might need it, because it exists, it is just not in the CRM.
Field mapping is where migrations are won
Before anyone opens an import tool, build the map. A spreadsheet with four columns: old field name, new field name, data type, and notes.
Go through it field by field. Most map cleanly. The ones that do not are the whole job:
Fields with no equivalent. Decide explicitly: recreate the custom field, merge the value into an existing field, or drop it. Write the decision down. "We will figure it out during the import" means it will be dropped silently.
Picklist values that do not match. The old system has seven deal stages, the new one has five. Someone has to decide where each old stage lands. If nobody does, the import either fails those rows or writes them as blank.
Date formats. Systems disagree about day-month-year order and about timezones. A date that reads as the third of April in one system and the fourth of March in another is a silent error that survives every automated check.
Owner assignment. Your user list is rarely identical across both systems. People have left. Someone needs to decide where records belonging to departed staff go, before the import, not after.
Clean the data in the old system while you are in there. Deduplicate on email address for contacts and on domain for companies, which are exact keys. Do not let a tool merge on similar names. A wrong merge attaches one company's history to another and is far harder to undo than a duplicate is to tolerate. This is the same principle that makes ongoing CRM hygiene work: exact keys or nothing.
Historical activity: what to keep and what to archive
Emails, calls, meetings, and notes are the heaviest and slowest part of any migration, and the part most likely to break.
Split it by whether someone will realistically open it.
Migrate activity on open deals and active accounts. A rep picking up a live conversation needs to see what was said last month. That is real working context.
For closed and dormant records, an export in storage is enough. A call note from four years ago on a deal you lost has almost no operational value, and carrying it across multiplies your import volume, your verification burden, and your chance of an association error.
The association part deserves attention. Activity records point at contacts, contacts point at companies, deals point at both. If those links break during import, you get an activity timeline attached to nothing, or worse, attached to the wrong account. Check associations explicitly in your test import, because no error report will mention them.
Run a test migration on real records
Import 50 records first. Real ones, chosen deliberately: a few simple contacts, a few with long histories, a few companies with multiple contacts and open deals, a few edge cases you know are strange.
Then open every one by hand and compare against the source. All of them. This takes an afternoon and it is the highest value afternoon in the project.
What you are looking for is whether each field landed with the right value, whether the associations survived, whether dates are correct, and whether picklist values mapped where you expected. A successful import status tells you none of that.
Fix the map, delete the test records, run it again. Two or three rounds is normal. Nobody gets the map right the first time.
And before the real import: turn off every workflow, sequence, and integration. All of them. To an automation, an import looks like thousands of new records arriving at once, and the resulting welcome email to your entire historical database is a genuine incident, not a hypothetical one. Turn them back on one at a time afterwards, checking enrolment criteria on each.
The parallel run period
Keep the old system available for two to four weeks after cutover. Not as a backup plan. As a reference.
One rule makes this work and breaks it if ignored: the old system is read-only from cutover day. Not "please try to use the new one." Read-only, enforced by permissions.
If two people can write to two systems, your data splits within a day. A deal updated in the old CRM and a different version of the same deal updated in the new one leaves you reconciling by hand, which costs more than the migration did and destroys trust in the new system permanently.
During the parallel period, do three things.
- Compare counts. Records by object and by owner, both systems, same day. Differences you cannot explain are unfinished work.
- Run your key reports in both. Pipeline value, deals by stage, activity by rep. If the totals disagree, find out why before you stop paying for the old system.
- Collect what people cannot find. Every "where did X go" question is either a missing field or a training gap, and both need answering while the old system is still open.
Set an end date and hold it. Parallel periods that drift past a month become permanent, and you end up paying two subscriptions while half the team quietly keeps using the old one.
The failures that repeat
Six specific things go wrong, over and over, and each has one check that prevents it.
- Unmapped custom fields. Prevented by the field map, not by the import tool.
- Mismatched picklists writing blanks. Prevented by deciding every value's destination before import.
- Broken associations. Prevented by checking relationships by hand in the test batch.
- Automations firing on import. Prevented by turning everything off first and re-enabling one at a time.
- Split data during parallel run. Prevented by making the old system read-only with permissions.
- Reports that do not match. Prevented by rebuilding reports deliberately rather than assuming they carry over, since every system calculates pipeline slightly differently.
Put one person in charge of all of it, with authority to say no. Migrations stall when every field question goes to a committee, and they bloat when nobody is allowed to refuse a request to bring something across. That person needs one sales contact and one marketing contact, and the right to make the final call. If your company is thinking about this move as part of a broader tech stack review, decide the ownership question at the same time.
For a company under 50 people moving between mainstream systems, four to eight weeks from first audit to full cutover is realistic. The import itself takes hours. Everything else is the decisions.
The takeaway
Decide what you are leaving behind. Build the map before you build anything else. Test on 50 real records and check them by hand. Make the old system read-only on day one.
Migrations do not fail loudly. They fail two weeks later when someone opens a record and a field is empty, and by then the project is closed and nobody is looking.