The “simple CSV cleanup” that became a relationship rebuild
A customer/contact import started as a small mapping problem and turned into a much deeper lesson about destination IDs, duplicates, record relationships, and why an import can succeed while the migration is still wrong.
It looked like a header problem
The project began with what looked like ordinary CSV import cleanup. A few records were failing, some references were invalid, and the obvious next step was to correct the mapping and rerun the file.
That explanation did not survive contact with the data. The more I compared the source files with the destination account, the clearer it became that the failures were symptoms of a relationship problem rather than a formatting problem.
The environment problem
Some references had been prepared against one NetSuite environment and then carried into another. Names looked familiar enough to make the data feel portable, but internal references are only meaningful inside the account where they were created. The destination needed its own authoritative mapping.
That meant comparing the destination customer records, identifying the correct references there, and then rebuilding the dependent contact/company relationships using the IDs that actually existed in the destination account.
Duplicates made the easy answer dangerous
Duplicate or near-duplicate entities made name-based matching especially risky. A contact could have a familiar company name and still point to the wrong record. In a few cases, lists and searches also surfaced data in ways that made the relationships look more straightforward than they really were.
This was one of the frustrating parts of the project: every time the dataset seemed ready for one clean import, another relationship or duplicate needed to be understood first. The right move was to slow down and reconcile the records rather than keep forcing rows through the importer.
The sequence that finally made sense
I treated the migration as a dependency graph. Parent records had to exist first. Child records came next. Relationship data came only after both sides were valid in the destination. Failed rows were separated and investigated instead of repeatedly mixing them back into the clean set.
After the imports, I exported the destination data again and compared what NetSuite actually contained with what the files were supposed to create. That post-import reconciliation caught issues that a green “success” result in the Import Assistant would never have shown.
What I learned
A successful CSV import is not the same thing as a successful migration. Row-level success tells you the importer accepted the data; it does not prove the resulting relationships represent the business correctly.
I also came away with a stronger preference for destination-grounded identifiers when relationships matter. Human-readable names are useful for review, but identifiers used for record relationships need to be validated against the environment where the records will actually live.
The outcome
By the end, the work had expanded far beyond a few headers, but the resulting customer/contact data was in a much better place: destination references were reconciled, relationships were rebuilt deliberately, duplicates were accounted for, and the final state was checked against fresh exports instead of assumed from the import log.
Data migration, CSV imports & reconciliation
See the broader service scope, common problems, and other related work.
View service