Mailerflow Start free
Blog › Email List Growth & Segmentation › Subscriber Management

How to Find and Merge Duplicate Contacts in Your Email List

Published November 14, 2026 · Updated November 15, 2026 · 7 min read

Illustration for How to Find and Merge Duplicate Contacts in Your Email List

Duplicate contacts in your email list are two or more records for the same person, and merging them means combining those records into one that keeps the strongest consent state and the union of engagement and profile history. The practical way to do it: normalize the email address, build a segment that surfaces collisions, decide a field-level merge rule, merge in small batches, then re-run the segment to confirm it returns zero. This guide walks through that process end to end, including how to verify the merge worked and how to stop duplicates from coming back.

Why duplicates in your email list are a data problem, not just a tidiness problem

A duplicate isn't a cosmetic issue. It splits one person's history across two records: opens and clicks on one, a newer job title on the other, a tag applied in one place but not the other. Your segment counts inflate, so "subscribers who clicked in the last 90 days" reports more people than you actually have. You pay for the same human twice on any plan that bills by contact, and you send them the same campaign twice in the same week.

The serious risk is consent. If Maria unsubscribed from record A but record B still shows as subscribed, your next send reaches someone who opted out. That's a deliverability problem and, depending on where she lives, a compliance problem. The same applies in reverse: a confirmed double opt-in on one record and an unconfirmed single opt-in on the other. Which one wins determines whether you can legally email her at all.

Duplicates usually arrive from three places: form re-submits (someone signs up again with a slightly different spelling), CSV imports that don't match existing records, and CRM or API syncs that write the same person under a new ID. The core rule for all three: a merge must preserve the strongest consent state and the union of history — never the record that happens to be newest.

Not sure your current tool is the right fit? Compare the Best Email Marketing Platforms by price, features and free plans for your exact list size.

What you'll set up and what you need

Before you touch any records, decide four things:

  • A unique identifier. Email address is the practical primary key, but it needs normalizing (lowercase, trimmed) before it can be trusted. Add a fallback — phone number or an external CRM ID — for people who change addresses.
  • A list of merge-worthy fields. Typically: consent status and timestamp, tags, custom fields, engagement counters, and suppression/bounce status.
  • A winner policy. Two common philosophies: keep-oldest (preserves the original consent timestamp, useful when the first record carries the confirmed opt-in) or keep-newest (preserves the latest profile data). Neither is right on its own.
  • A field-level merge map. This is the recommendation: instead of letting one whole record win, decide per field. Consent comes from the record with the most recent confirmed opt-in. Tags are the union. Custom fields take the most recently updated non-empty value. Engagement counters are summed.

One prevention note before you start: Mailerflow's CSV import runs duplicate and validity checks, which stops most new duplicates at the door. If you're still bringing a list in, the import walkthrough covers how matching keys work in practice.

Step-by-step: finding and merging duplicates

  1. Export or open the contact table and sort by email. Even a rough alphabetical sort surfaces obvious pairs — maria.lopez@ next to Maria.Lopez@. This is a sanity check, not the real detection method.
  2. Build a duplicate-detection view. In Mailerflow, create a dynamic segment filtered on a normalized email field. If your platform doesn't normalize automatically, add a custom field called dedupe_key and populate it with the lowercased, trimmed email on every write. Then the segment is simply "dedupe_key appears more than once." Dynamic segments on fields, tags, engagement, events and website behavior can hold this filter permanently, so new collisions show up on their own.
  3. Define the match rule. Start with exact match on the normalized email. Then handle near-duplicates separately: fuzzy match on name plus company, or on phone number. Decide explicitly whether maria+news@example.com is the same person as maria@example.com — plus-addressing usually is, a typo'd domain usually isn't.
  4. Decide the surviving record and the field-level merge map. Write it down before you merge anything. Example rule set: consent = most recent confirmed opt-in; tags = union of both; custom fields = most recently updated non-empty value; engagement = sum of opens and clicks; last activity = the later of the two dates.
  5. Merge. For small batches, a manual merge in the UI is fine. For larger sets, use the import path with duplicate checks enabled, or the REST API with scoped keys and idempotency keys — the idempotency key matters because a retried merge job won't create a second record if the first attempt partially succeeded.
  6. Re-run the duplicate segment. It should return zero contacts for that match rule.
  7. Log the merge. Date, rule applied, number of records merged. You'll want this if a subscriber ever asks what happened to their preferences.

A worked example: two records for the same subscriber

This example is invented to show the mechanics.

Contact A — maria.lopez@example.com, created 2024-03-02, double opt-in confirmed, tags [newsletter, webinar-attendee], 14 opens, 3 clicks, last activity 2025-11.

Contact B — Maria.Lopez@example.com (capital L, trailing space), created 2025-06-18, single opt-in from a lead magnet form, tags [lead-magnet], 0 opens, no consent timestamp.

Field Contact A Contact B Merged record
Email maria.lopez@example.com Maria.Lopez@example.com (trailing space) maria.lopez@example.com
Created 2024-03-02 2025-06-18 2024-03-02
Consent Double opt-in confirmed Single opt-in, no timestamp Double opt-in confirmed (from A)
Tags newsletter, webinar-attendee lead-magnet newsletter, webinar-attendee, lead-magnet
Job title (empty) Head of Ops Head of Ops (newer non-empty)
Opens / clicks 14 / 3 0 / 0 14 / 3
Last activity 2025-11 — 2025-11

The anti-pattern to avoid: deleting B and re-importing its data into A. That wipes B's consent log, which is the one piece of history you can't reconstruct. Merge, don't delete-and-recreate.

How to check the merge actually worked

Run this checklist after every batch:

  • The duplicate segment returns 0 contacts for the match rule you applied.
  • Your total contact count dropped by exactly the number of merges. If it dropped by more, you merged records that weren't duplicates.
  • Spot-check three merged records for tags, consent timestamp, and custom fields against the merge map you wrote down.
  • Confirm the merged contact still appears in the segments it belonged to — for example, webinar-attendee should still include Maria.
  • Check that no automation was mid-flight for the deleted record ID. A contact who was three days into a five-day wait sequence needs to continue on the surviving record, not restart.
  • Confirm suppression and bounce status carried over. A hard bounce on either record should suppress the merged one.

Mailerflow's analytics for delivery, bounces and complaints are tracked per contact, so a correctly merged record shows the combined history rather than a reset to zero.

Common mistakes and how to fix them

  • Merging on raw email without normalizing. Case and whitespace differences hide duplicates. Fix: maintain a dedupe_key field on every write.
  • Letting the newest record win by default. This can overwrite a confirmed double opt-in with an unconfirmed one. Fix: field-level consent rules, always.
  • Deleting the loser before exporting its tags and custom fields. Fix: export first, merge second.
  • Re-importing the loser's data as a new contact. Usually caused by matching on the wrong key during import. Fix: confirm the match key before you upload.
  • Ignoring near-duplicates. Typo'd domains and plus-addressing need an explicit decision, not a default.
  • Not re-checking segments afterward. Stale membership lingers if the merge didn't propagate. Fix: re-run the duplicate segment and one or two key segments as a spot check.

Preventing duplicates from coming back

Merging is the cleanup; prevention is the system. Four levers do most of the work:

  1. Signup forms that update instead of create. Embeddable signup forms with double opt-in and consent records mean a re-submit matches the existing contact and refreshes their consent log rather than spawning a twin.
  2. Import with duplicate and validity checks on. This is the single highest-value setting if you import regularly.
  3. API writes with idempotency keys. Any sync job that retries should be safe to retry.
  4. A standing "possible duplicates" segment. Build it once on the normalized key and let it flag new collisions automatically. If you'd rather not hand-build the filters, AI segmentation from a plain-language description can create that segment for you — describe what a duplicate looks like and review the result.

FAQ

Does merging contacts lose their consent record? Not if you merge rather than delete-and-recreate. Set the rule so consent comes from the record with the most recent confirmed opt-in, and the merged record inherits it. Deleting a record is what destroys the consent log.

Should I merge or delete duplicates? Merge when either record has history worth keeping — engagement, tags, custom fields, or a consent timestamp. Delete only when a record is genuinely empty and clearly created by mistake.

How often should I dedupe an email list? Run the duplicate segment monthly, and immediately after any large import or CRM sync. Continuous detection beats an annual cleanup.

What about duplicates across two different lists? If your platform treats lists as tags on a single contact record, a merge handles it. If lists are separate silos, you'll need to merge within each and then decide which list membership the person should keep.

Can I undo a merge? Usually not cleanly. The practical undo is an export of both records taken before you merge. Make that export a standard part of the process.

Next steps

Run your duplicate segment today and see what it returns. Merge in batches of 50–100 so you can verify each batch against the checklist before moving on, then set up the prevention levers — normalized keys, import checks, and a standing duplicates segment. If you're bringing a messy list over from another tool, Mailerflow offers free migration help (contacts, suppression lists, templates, core automations) on eligible paid plans, and the import guide covers the matching rules in detail.

Add an embeddable signup form with double opt-in and build dynamic segments in Mailerflow — start free.

Further reading