Finding duplicate people in a 1.2M-record CRM
From my résumé Figures from my résumé; examples are made up
Business rules, analysis and QA for a nonprofit CRM deduplication: who counts as the same person, how sure we need to be before merging, and the checks every merge file had to pass.
- Status
- My job at EDF · no employer data shown
- Relevant to
- Data engineering, CRM and RevOps
Results · Figures from my résumé; examples are made up
- From my résuméFrom my résumé, for my job at Environmental Defense Fund. The records, queries and internal figures behind it stay private.records in the deduplication effortFrom my résumé
- From my résuméFrom my résumé, for my job at Environmental Defense Fund. The records, queries and internal figures behind it stay private.more candidate duplicate pairs found with the new rules, from about 50K to about 68K (rounded)From my résumé
The problem
The CRM’s built-in duplicate matching missed people who appeared more than once under slightly different names, emails or addresses. A wrong merge is hard to undo: it combines two real people’s histories and their consent to be contacted. The organization needed to find more duplicates without raising that risk.
My role
I wrote the business rules for the matching, analyzed how the existing matching behaved and where it missed, and ran the QA, including which ID survives as the primary record and the checks every merge file had to pass. The matching itself was run by an outside data vendor.
How it works
1.Candidates
Compare only records that share a blocking key, such as a normalized email, phone or name plus ZIP, so the work scales.
2.Score
Score each candidate pair on how closely names, emails, phones and addresses agree, with nicknames and formatting differences handled.
3.Tier
High-confidence pairs can merge automatically. The middle tier goes to a person. Low scores are not treated as matches.
4.Review
A person reviews the middle tier and anything the rules flag as risky.
5.Group
Link pairs into groups, so if A matches B and B matches C, all three become one person with one decision.
6.Map and check
Pick one primary ID per group, map every other ID to it, and run the merge-file checks before anything merges.
What I built
- Business rules for what makes two records the same person, written so the vendor could implement them and we could test them.
- An analysis of the existing matching: which kinds of duplicates it caught and which it missed, used to set the new rules.
- Confidence tiers that separate automatic merges from merges a person reviews.
- Grouping of linked pairs into one person through their connections, and a mapping from every duplicate ID to one primary ID.
- Merge-file QA: checks every file had to pass before it went back to the CRM.
- Findings written up for leadership.
Example
| Pair | What agrees | What differs | Tier |
|---|---|---|---|
| Maria Lopez / María López | Email, phone, ZIP | Accent in the name | Automatic merge |
| Jon Smith / John Smith | Phone | Email, ZIP | Person reviews |
| Pat Lee / Pat Lee | Name only | Email, phone, city | Not a match |
| A ↔ B, B ↔ C | A and C never compared directly | One link is weaker | Grouped, person reviews the weak link |
Decisions and tradeoffs
- Scored matching over exact rules alone
- Exact matches on email are safe but miss the same person with a new email or a typo. Scoring finds more, and the tiers decide how much risk is acceptable.
- Precision over recall for automatic merges
- A missed duplicate costs a duplicate mailing. A wrong merge combines two people’s histories and consent, so the automatic tier only takes pairs we are very sure about.
- Group first, then decide
- Merging pair by pair can give conflicting answers for the same person. Grouping linked pairs first gives one decision and one primary ID per person.
- Watch for weak links in groups
- Linking through connections can chain two different people together through one weak pair, so groups held together by a weak link go to a person.
Validation
- Every merge file had to pass the QA checks before it went back to the CRM: for example, every duplicate maps to exactly one primary, and no ID is both a primary and a duplicate.
- The new rules were compared with the old matching to see what each found, so the increase in candidates was measured, not assumed.
Limitations
- Described without employer data: the records, IDs, queries and scoring weights stay private. The example rows are made up.
- The vendor ran the matching itself. My part was the rules, the analysis and the QA.
Why it matters for the job
Identity resolution is the core of CRM data quality, customer data platforms and RevOps reporting: every count of customers, members or leads depends on knowing who is the same person.
Stack
Snowflake, SQL, Snowflake Cortex, EveryAction/VAN
Related work
- Choosing the right phone number for every supporter
My job at EDF · no employer data shown
- Finding 44K members missing from the CRM
My job at EDF · no employer data shown
- Finding duplicate contacts in a CRM
Code on GitHub