Implementation worksheet · 6 min read
A Duplicate Record Resolution Workflow for a Lightweight CRM
Write three things down before you write any matching code: the match rule (which fields, at what confidence, and the threshold above which a match is automatic versus queued for review), the survivorship table (for every field, which record's value wins — newest, non-empty, primary record, or manual), and the merge record (what is kept so the merge can be explained later, and whether it can be reversed). Most CRM duplicate problems are actually missing survivorship rules: the merge ran, it picked a value by an implicit rule nobody chose, and a correct email address was silently replaced by a stale one.
Every CRM accumulates duplicates — the same person from a form fill, an import, and a manual entry, with three spellings and two email addresses. Hosted CRMs offer a merge button and a guess. For a lightweight or custom CRM the merge policy is yours to define, which is an advantage only if you define it deliberately rather than discovering it during an argument about whose phone number is correct.
Put it into practice
1. Decide what makes two records the same thing
Email exact match is high confidence. Name plus company is medium. Phone alone is low and generates false positives on shared office lines. Write the field weights and two thresholds: above the high one merge automatically, between them queue for a human, below it do nothing. Automatic merging with one loose rule is how you join two different people at the same company.
2. Build the survivorship table before the merge button
Field by field: email, phone, company, owner, lifecycle stage, notes, custom fields. For each, state the winning rule. 'Newest non-empty' is a reasonable default for contact details, 'primary record' for ownership, and 'concatenate' for notes and activity. Any field where you cannot pick a rule should be flagged for manual review rather than guessed.
3. Keep activity history additive, never overwritten
Emails, calls, notes and deal history should union, not pick a winner. This is the rule teams break — usually by merging the record rather than the timeline — and it is the one that cannot be recovered from once the losing record is deleted.
4. Record the merge as an event
Which records merged, when, by whom or by which rule, and the field-level before values. Without this you cannot answer 'why does this contact have the wrong email' three weeks later, and you cannot reverse a bad automatic merge. Soft-delete the losing record for a retention window rather than hard-deleting it.
5. Prevent at intake, not just at cleanup
The same match rule runs on create. A form fill matching an existing contact updates it instead of creating a second one; an import runs the rule per row and reports what it matched before it commits. Dedupe as a periodic cleanup job is treating the symptom — the intake path is where the duplicates come from.
The survivorship table
Copy this structure into your review document and record your observed result for each row.
| Field | Winning rule | On conflict | Reviewed |
|---|---|---|---|
| Email (primary) | newest non-empty | queue for review | |
| Email (secondary) | keep both | n/a | |
| Phone | newest non-empty | keep both | |
| Company | primary record | queue for review | |
| Record owner | primary record | notify both owners | |
| Lifecycle stage | furthest along | furthest along | |
| Notes and activity | union, never replace | n/a | |
| Custom fields | newest non-empty | queue for review | |
| Consent and subscription state | most restrictive wins | most restrictive wins |
A failure worth checking
Merging consent by the same rule as contact details. Record A is unsubscribed, record B was imported with consent assumed, the merge takes 'newest non-empty', and a person who opted out is now subscribed again. Contact details tolerate a newest-wins rule; consent and suppression state do not — the most restrictive value must win regardless of recency, and that exception belongs in the survivorship table as its own row, not in someone's memory.
Common questions
Should merges be automatic or reviewed?
Both, split by confidence. Exact email match is safe to automate and reviewing it wastes the reviewer. Fuzzy name matches should queue. The threshold between them is a judgement call you should be able to change without a code change, because the right value depends on how messy your intake is.
Can a merge be undone?
Only if you planned for it — field-level before values plus a soft-deleted losing record. Retrofitting reversibility after a bad bulk merge is not possible, which is why the merge event is on this list rather than the nice-to-have list.
Basis and scope
This is a proposed implementation method using illustrative examples, not a measured benchmark or a customer case study. Prepared with AI assistance. Validate product-specific behavior against current documentation and your own test environment.