Every data migration gets tested at cutover. Record counts match the source system, a sample of accounts and contacts gets eyeballed, a handful of business users click through their most important records and confirm nothing looks obviously wrong. Hypercare runs for two or three weeks, the incident count stays low, and everyone moves on. Then, somewhere around month three, the real problems start showing up. And by then nobody’s thinking about the migration anymore, so the first instinct is to blame the new automation, or the new integration, or “something Salesforce changed.”
It’s rarely Salesforce. It’s usually the migration, and the reason it took three months to notice is that the mistakes that matter aren’t the ones cutover testing is built to catch.
Why cutover testing misses the damage that matters
Cutover validation answers one question: did the records land? Count comparisons, field-level spot checks, a UAT pass against a sample. All of that is necessary. None of it tests what happens once real users, real automation and real time start interacting with the migrated data. The bugs that surface later aren’t data quality bugs in the traditional sense. They’re mismatches between what the migration assumed and what the org actually does with a record over its lifecycle.
I’ve seen this pattern often enough on enterprise orgs that I now treat it as the default outcome of any migration that only tests for “did it land correctly,” rather than “will it behave correctly.”
The five mistakes that don’t show up on day one
Backdated CreatedDate breaking date-based automation
Migrated records usually carry their original creation date, which is the right call for reporting. But entitlement processes, SLA timers, and any flow with a time-based path built on CreatedDate or a derived field will behave differently for a record created three years ago versus one created this morning. A case migrated with its original 2023 timestamp can slip straight through an SLA escalation that was designed around cases created after go-live. Nobody notices during hypercare because hypercare is full of freshly created records, not migrated ones. It shows up the first time someone runs an aged-case report or an escalation fires (or doesn’t fire) on a record nobody remembers was migrated.
Ownership that technically works but breaks sharing
A common shortcut: assign every migrated record to the integration user or a generic “Data Migration” user, then reassign in a follow-up script. When that follow-up step is incomplete, or when territory and queue assignment rules only fire on record creation (not on data load), you end up with records that are visible to the wrong people, invisible to the right people, or sitting in a queue nobody’s monitoring. This one is genuinely hard to catch at cutover because sharing visibility depends on who’s looking. A system admin testing UAT sees everything. The actual case owner three months later doesn’t.
External IDs that aren’t as unique as they look
If the migration used an external ID field to support future upserts from an integration, and that field wasn’t validated for true uniqueness against production edge cases (leading zeros stripped, whitespace, case sensitivity on a text field instead of a proper external ID field), you get silent overwrites. The first few weeks nothing collides because the integration is dealing with genuinely new records. Then a legacy record with a near-duplicate key gets touched by an inbound sync and quietly overwritten. Nobody gets an error. The data is just wrong, and it stays wrong until someone happens to compare it against the source system.
Roll-up and formula fields that drift instead of break
Roll-up summaries recalculate on the trigger events they’re built for: a child record inserted, updated or deleted. A bulk data load that doesn’t fire those events in the expected order, or that loads parent and child records out of sequence, can leave a roll-up value that was correct on migration day and never gets touched again unless something forces a recalculation. Three months in, someone compares a roll-up total against the underlying child records and finds a gap. It’s not corruption. It’s a number that was right once and nobody ever asked Salesforce to check it again.
Validation rules disabled for the load and never fully restored
Almost every migration disables validation rules, and sometimes triggers, to get bulk data through without a wall of errors. The riskier version of this is when a rule gets disabled at the metadata level rather than bypassed for the load user specifically, and re-enabling it becomes a manual step buried in a cutover runbook that doesn’t get checked off with the same rigor as the actual data load. Bad records start entering the system weeks later through completely normal channels, because the guardrail that should have stopped them was never switched back on.
Catching these before they’re three months old
None of this requires exotic tooling. It requires treating the first ninety days after go-live as part of the migration, not the period after it.
- Before the load, list every automation with a time-based or CreatedDate-dependent path and decide explicitly how migrated records should behave against it, rather than discovering the answer in production.
- Test sharing visibility as the actual end users who will own the records, not as a system admin. Profile-level testing catches what UAT with a full-access login won’t.
- Run a uniqueness and format audit on any field used as an external ID or upsert key, against real edge cases from the source system, not a clean sample.
- Force a full recalculation of roll-up and formula fields after the load completes, then reconcile a sample against the source rather than assuming the load triggered it correctly.
- Put “validation rules and triggers restored to pre-migration state” on the cutover checklist as its own signed-off line item, with a metadata diff to prove it, not a verbal confirmation.
- Schedule a deliberate data health check at thirty, sixty and ninety days post go-live. Nobody plans for this, which is exactly why it catches things.
The teams that get burned by this aren’t careless. They’re just measuring the wrong moment. A migration that “worked” on go-live day and a migration that holds up at day ninety are different things to test for, and only one of them is the one your users actually experience.