Duplicate records are treated as a tidiness problem. They are a reporting and decision problem. Two contact rows for one person means two histories, two owners, two sets of open work, and a pipeline number that is wrong in a direction nobody can measure.
The worse version is not the duplicate you can see. It is the record split three ways, where each part looks complete enough that nobody investigates.
Where duplicates actually come from
Duplicates arrive through three doors, and each door needs a different mechanism. Treating them as one problem is why cleanup projects have to be repeated every year.
Creation without a check. Someone searches, does not find, and creates. Almost always because the search did not match how the record was originally spelled. This is the most common source and the cheapest to fix, because the moment of creation is the moment you have the person’s attention.
Imports without a match key. A CSV loaded with no decision about what counts as an existing record. This is the highest-volume source: one import can double a table in a single action.
Identity differing across channels. The same human submits a form with a work address, chats using a personal address, and is invoiced to an accounts inbox. Three touchpoints, three identifiers, and nothing in the data says they are one person.
Deterministic and probabilistic matching are different tools
Deterministic matching compares a stable identifier. Two records with the same email address, the same tax registration number or the same external system ID are the same record, and the comparison has no confidence score because there is nothing to be uncertain about.
Probabilistic matching scores similarity across weak fields: name proximity, same company, same phone with different formatting, same domain. It returns a likelihood, not an answer.
The rule that follows is not a style preference. Deterministic matches are safe to act on automatically because a false positive requires two records to genuinely share a unique key. Probabilistic matches must produce a suggestion for a human, because the false-positive case is two different people at one company with similar names, and merging them destroys one person’s history inside the other’s record.
| Mechanism | What it compares | Acceptable action | Failure if misused |
|---|---|---|---|
| Deterministic, unique key | Email, tax number, external ID | Block the create, or merge automatically | Rare, and traceable to the key itself |
| Deterministic, non-unique | Domain, company name exactly equal | Group and warn | Treats colleagues as one person |
| Probabilistic | Name, phone, address similarity | Suggest to a person, never act | Silently merges two real customers |
| No matching | Nothing | None | Duplicates accumulate at the rate of use |
In Oneop, contacts, deals and activities each expose a duplicate check that the form calls while you are typing, so the common case, a person recreating a record they could not find, is caught before the row exists rather than in a cleanup pass three months later.
Merge is destructive, so the preview is the safety mechanism
A merge answers three questions at once: which record survives, which field values survive, and what happens to everything linked to the losing record. Most merge interfaces answer the first and leave the other two to be discovered afterwards.
The second and third are where the damage lives. A merge that keeps the wrong email address breaks every future match on that person. A merge that combines linked records instead of re-pointing them changes what those records mean.
In Oneop’s CRM, contacts, companies and leads have a merge flow that renders the outcome before committing it: which value survives on each field, which value is discarded, and which linked records will be re-pointed at the surviving row rather than combined. That distinction matters more than it sounds. A deal, a ticket and an invoice do not merge, they move. Seeing the count of records about to be re-pointed, before pressing anything, is the difference between a merge you can approve and one you have to regret.
Why an unmerge has to exist before merge is safe
Here is the argument in one line: merge is a destructive operation triggered by a judgement call, and every such operation needs a path back.
Consider two contacts named Sam Ahmed at the same manufacturer, one in procurement and one in engineering, sharing a shop email address that was used for both. A probabilistic matcher scores them as the same person. Someone merges. The procurement history, the quotes, the payment terms conversation and the engineering support tickets now sit in one record with one owner. Six months later the two people are clearly two people, and there is no field that says which history belonged to whom.
Without an unmerge, recovery is manual reconstruction from memory and email archives. That is not a data operation, it is an archaeology project.
The honest position on Oneop here is the preview rather than an undo: the merge shows exactly what will happen before it happens, which is the mechanism the product actually has. The one true reversal in the platform sits on imports, where an admin can roll an entire import back completely within thirty minutes. If you are evaluating any CRM, ask the reversal question directly and treat a vague answer as a no.
Import discipline, because one file outweighs a year of typing
Manual creation produces duplicates at the speed of human work. An import produces them at the speed of a file.
Three rules make imports safe. Decide the match key before the file is loaded. Validate the entire file before writing a single row. And require an explicit decision about what happens when a row matches something that already exists.
Oneop imports twenty-two record types from CSV, spanning CRM, support, finance and inventory. Every import runs a validation pass first and reports total, valid, invalid and duplicate row counts before anything is written, and you choose whether duplicates are skipped or overwritten. The thirty-minute admin rollback exists because the correct response to a bad import is almost never row-by-row repair. Exports are neutralised against formula injection on the way out, which is a different hygiene problem with the same cause: a spreadsheet trusted as a data-interchange format.
The fragmented record, which no duplicate audit finds
Fragmentation is the failure worth designing against, because it hides from the tools built for duplicates.
A real example of the shape. A customer exists three times. The sales record was created from a web form with a work email and holds two deals and a call log. The support record was created from an inbound email sent by the same person using a different address, and holds nine tickets. The finance record was created when the first invoice was raised, using the accounts inbox, and holds the payment history.
No duplicate detector flags any of these, because all three identifiers differ. Each record looks complete to the team that owns it. And every question that spans two of them gets a wrong answer: the account manager preparing a renewal sees a clean relationship and no support load, the support lead sees a demanding account with no revenue attached, and any churn-risk analysis reads three quiet accounts instead of one loud one.
The structural fix is not a better matcher. It is that there should only be one record to begin with. In Oneop a ticket’s requester resolves to the same CRM contact that the deal and the invoice reference, matched by email inside the workspace boundary, with no sync job and no field mapping, because nothing is duplicated. The help desk also refuses to open a second ticket for an inbound message ID already seen in your workspace, backed by a unique index scoped to that workspace. It is worth knowing the boundary too: Oneop has no ticket merge, and the ticket screen instead surfaces up to six likely-related open tickets, same requester first, then same company, then a shared tag. That is a lookup, not a rule.
The wider architectural case is in what an AI-first customer platform actually is, and the channel-level version, where the same person arrives by chat and by email, is in running a two-channel support operation.
The maintenance loop that keeps it clean
Hygiene is a standing process, not a project, and it needs three things running.
Prevention at creation, which is the duplicate check on the form. Controlled intake, which is import validation with an explicit duplicate decision and a rollback window. And detection after the fact, because the first two will never be perfect: a scheduled report of probable duplicates, reviewed by a person who is allowed to decide.
Put the detection report in front of the same people who use the records. A queue reviewed by whoever owns the account beats a quarterly cleanup by an operations hire who has never spoken to any of these customers. Reporting is the natural home for that list, and integrations that write into your CRM deserve the same scrutiny as any import, because a connector with no match key is an import that runs every day.
Duplicates are not a sign of a sloppy team. They are what happens when the system lets two rows exist for one relationship. Fix the mechanism, and the tidying stops being annual.