Back to Blog
HubSpotRevOpsData Quality

Auditing a B2B CRM: duplicate contacts, broken associations and the structure to rebuild (2026)

Abhishek Singla Nov 1, 2026 14 min read

A CRM audit that starts by merging records is already going wrong. Duplicates and broken associations are output, not input. Something created them, and in almost every case that something is still running: a sync app writing companies through the API, an import file missing its unique identifier, a setting that mints one company record per subdomain. Merge first and you spend a week cleaning a pipe that is still filling. The sequence that holds is the reverse: count what is there, read how it got there, close the creation path, then repair. HubSpot documents every mechanism involved, including the ones that cannot be undone.

The short answer

Audit in four counts before changing one record: duplicate pairs against HubSpot's default matching properties, formatting and property-fill issues, the association history on a sample of records, and an inventory of every path that creates records. Then close the creation paths, because companies created through the API are not deduplicated by domain at all. Then merge, knowing a merge cannot be reversed, rewrites property timestamps to the merge date, and unenrolls records from active workflows. Then set association limits so the structure refuses the next bad association instead of training people not to make it.

Each of those is documented rather than preferred. HubSpot states that companies created through the API, including installed third-party sync apps, are not deduplicated by company domain name. It states that merges cannot be unmerged, and that the automatic company association setting creates a separate company for every unique subdomain. And it gives you association limits, per object pair and per label, that users cannot exceed once saved.

What should a CRM audit measure before anything is changed?

Four counts and one map. The counts are duplicate pairs, formatting issues, property fill and usage, and association integrity. The map is every route by which a record comes into existence.

HubSpot gives you the first three in one place. HubSpot's article on using the data quality tools, last updated 26 June 2026, describes a data quality overview page with a summary showing the change in duplicate and formatting issues across a date range, a recommended actions block listing duplicates detected by Breeze, formatting issues by property and unused workflows, and a property insights chart plotting total properties against three issue types: duplicates, no data, and unused. Viewing it needs Super Admin, or data quality tools access with view permissions; fixing records there needs view-all permissions on contacts and companies.

Two details change how you should use that page. The duplicate alerts table counts against a limit you set yourself, your account is checked every 24 hours, and the figures show the total at the moment the notification was sent rather than updating as you clean up. And once a record has been corrected there, HubSpot says that if it is later updated manually in an incorrect format, the overview page will not flag it again. Treat it as a baseline read rather than a monitor: export the duplicate list to CSV, XLS or XLSX at the start, and count again at the end against that same file.

Measure first because the cost of bad CRM data is already being paid, usually in the forecast. Validity's The State of CRM Data Management in 2025, drawing on 602 CRM users and stakeholders, reports that 37% of CRM users lost revenue as a direct consequence of poor data quality and that 76% said less than half of their organisation's CRM data is accurate and complete. Those are self-reported perceptions rather than measured counts, which is why your own four counts matter: they turn an argument about whether the data is bad into a number nobody disputes.

What an audit costs tracks those counts rather than a page rate: record volume per object, objects activated, integrations holding write access, properties existing against properties used, and whether association labels already exist. Any fixed figure quoted before those are known is a guess, and no public range read for this guide was credible enough to print.

How do you find the duplicate contacts and companies you actually have?

Start with HubSpot's own matcher, then narrow it, because the default rule is deliberately broad.

HubSpot's guide to reviewing and managing duplicate records, last updated 23 October 2026, names the properties the default rule compares. For contacts: First Name, Last Name, Email address, IP country, Phone number, Zip Code and Company Name. For companies: Company Domain Name, Company Name, Country/Region, Phone Number and Industry. HubSpot recalculates as contacts and companies are created, and checks once daily on days when nothing is created.

The number the tool shows is capped, and the cap is easy to mistake for a count. Professional and Enterprise surface up to 10,000 duplicate pairs and allow individual management. Bulk management and larger ceilings need Data Hub: Professional raises it to 30,000 pairs, Enterprise to 100,000. If your duplicates figure sits exactly on one of those numbers, you are reading the ceiling.

Narrowing is where the audit gets real. The same article says the duplicates table filters by owner, create date, similarity, last activity date, discovered date and lifecycle stage, and explains why the similarity filter is more granular for contacts than companies: contact property data points carry higher variance, so more bands are offered, down to thirty percent and up, for pairs that are not immediately identifiable. Custom detection rules need Data Hub Professional or Enterprise and allow up to two rules per object across up to nine properties. HubSpot warns you when a rule matches more than 10% of all records in the account with an average group size above three; the rule still saves, but searching and filtering the duplicates table may not return complete results at that scope, which makes a too-broad rule misleading rather than merely noisy. In practice the rules that earn their place are built on a unique external identifier, a phone number or a custom ID property, not on name fields.

What does merging actually do to your data?

More than most teams expect, and one part of it is permanent.

HubSpot's article on merging records, last updated 5 September 2026, is unambiguous: it is not possible to unmerge records. The remaining record combines activities, associations and most property values from both. By default a new Record ID is generated, with the original IDs preserved in the Merged [record] IDs property, which an is-known filter turns into a list of every record ever merged. A public beta called Primary ID Preservation for Merged Records keeps the primary record's ID instead, which matters if any API or webhook keys off Record ID.

The behaviours worth writing into a runbook before any bulk merge:

  • Property values: the primary record's values win, except where the primary has no value, in which case the secondary's is used. Property history from both is combined, and the create date keeps the older of the two.
  • Property value timestamps: when a merge updates a value, the timestamp shown is the time of the merge, not the original date from the source record. Any report trending a property over time is altered by the merge itself.
  • Associations: all associated records from both appear on the result. For company associations carrying the Primary label, the primary company from the primary record wins, and the secondary record's primary association stays attached but loses the label.
  • Contacts: the secondary email becomes a secondary email address, lifecycle stage keeps whichever is furthest down the funnel, number of conversions and number of unique forms submitted are added together, the most marketable marketing contact status is kept, and legal basis keeps the most recent values from both records.
  • Companies: the secondary domain becomes a secondary domain name, lifecycle stage again keeps the furthest down the funnel, analytics properties are re-synced to combined totals, and original traffic source keeps the oldest value unless it was manually set.
  • Workflows: unless the account is in the Primary ID Preservation beta, both the primary and the secondary record are unenrolled from their active workflows at the time of the merge.

That last one is the quiet one. A bulk merge across a few thousand contacts empties nurture sequences, stalled-deal timers and routing workflows mid-flight, and nothing in the duplicates table warns you. Decide beforehand which workflows need re-enrolment, and check whether your settings allow contact enrolment from merges.

Merges also fail, for four documented reasons: the records have been involved in a combined total of 250 or more merges, the result would exceed your configured association limits, the companies sit in a parent-child relationship containing a loop, or the account runs the old HubSpot and Salesforce integration, which does not permit company merges. Allow up to 30 minutes after a merge for activities to sync.

Choose the survivor deliberately. Bulk merging offers five criteria: most recent engagement, oldest engagement, created first, created last, and most recently updated. Custom merge rules go further, with up to five criteria evaluated in order until one produces a winner, drawn from property conditions, most associated objects, most activities logged and highest fill rate, plus a tie-breaker and up to 20 property overrides. For a B2B database, most associated objects or highest fill rate usually preserves more truth than created first, because the oldest record is often the thinnest one. Rejections are recoverable for 14 days, but only if the records were not edited in the meantime, and a rejected pair can reappear if one of its records is later merged into something else. Merge history exports cover 90 days, only for merges performed in the data quality tool.

Why do the duplicates come back after you clean them up?

Because duplicates are produced by creation paths, and merging does not touch a single one of them. This is the section of the audit that actually changes the trend line.

HubSpot's article on deduplicating records, last updated 2 October 2026, explains what the automatic deduplication covers: contacts are deduplicated by email address, companies by their primary company domain name. Then it names the hole. Companies created through the API are not deduplicated by the Company domain name property, and HubSpot states that this includes installed third-party sync apps. If a data sync app, an enrichment tool or a custom integration creates companies, the platform's own safety net is not under it.

Imports are the second source, and they are mechanical. An import without the Email property or another unique identifier creates a new contact for every row, and one without the primary or secondary company domain name or a custom unique ID creates a new company for every row. If several records already exist with the same email or domain, the import errors on that row and skips it rather than guessing. With a Record ID column included, rows holding no Record ID value create new records. One specific trap: where the file carries both a secondary email column and a Record ID column and the secondary email is the unique identifier, the secondary email replaces the primary email on the existing contact, and leaving the Record ID column out prevents that overwrite.

The third source is a setting that looks like hygiene and behaves like a duplicate factory when the data underneath it is inconsistent. HubSpot's documentation on automatically creating and associating companies with contacts, last updated 26 June 2026, says a company record is created for each unique domain including subdomains, so contacts at example.com and info.example.com end up on two different company records. Where several companies already share a domain name, contacts with that domain are automatically associated with only one of them, and HubSpot states you cannot choose which. Freemail addresses fall through to the contact's Website URL property. HubSpot also advises against turning the setting on alongside the Salesforce integration, because it can produce duplicate company records. Up to 1,000 domains can be excluded, and removing a domain from that opted-out list only takes effect after the setting is toggled off and back on.

The structural fix is a uniqueness constraint rather than a cleanup habit. Each object supports up to ten custom properties that require unique values, enforced on manual creation and editing and on import. The gap to plan around: unique value properties are not supported in forms, so form-created records still fall back to email, company domain name and Record ID. The recurring cadence that keeps this from drifting again is a separate discipline, argued in our guide to CRM data decay and the hygiene system that stops it, and the ownership question behind it in our guide to data governance for B2B revenue operations.

What counts as a broken association, and how do you find them?

Four shapes, and only the first is obvious: a missing association, a wrong one, an unlabelled one, and a correct association that is not the primary.

That last shape does damage quietly. HubSpot's article on associating records, last updated 16 September 2026, describes Primary as a default one-way label on object-to-company relationships. For contacts, the first company associated becomes primary by default, and a contact with only one associated company cannot have that label removed. What hangs off it is substantial: timeline activities are automatically associated with only the primary company, the optional lifecycle stage sync updates only the primary company's stage, and the primary association is what segments, workflows and cross-object reports reference. A contact on the wrong primary company is therefore not a cosmetic error. It files their calls and emails against the wrong account and reports their lifecycle there too.

To find the breakage, read the history rather than the current state. On any record, Actions then View association history opens a panel that filters by object type and shows, per row, the update to the association, including object deleted, association label added or changed, and association created, alongside the source, meaning the user name or ID, and the date. That is how you answer who broke this and when, which is usually the difference between a repair and a repeat.

For breadth rather than depth, the index page carries the same work in bulk. Select up to 100 records, click Review Associations, filter by association type and by label, expand all rows, select the ones to cut, click Dissociate, then type the number of associations being removed and confirm. That typed confirmation is deliberate friction worth respecting. Associations in HubSpot are always two-way, so there is no half-broken link to tidy up: anything that looks like one is usually a deleted record or a removed label, which the history panel will show you. Association labels need Professional or Enterprise, and managing associations needs Super Admin or the edit associations permission.

How do you repair associations in bulk instead of one record at a time?

Four mechanisms exist, and the choice between them decides whether the repair can be reversed.

HubSpot lists importing with one or two files, the associations API, the domain linking setting, and workflows. For a repair pass, workflows are usually right because they can be scoped, re-run and unwound. HubSpot's guide to creating and managing CRM record associations with workflows, last updated 23 September 2026, documents three actions: create associations, apply association labels, and remove association labels. They need Professional or Enterprise plus Super Admin or workflows permission, and they cover contact, company, deal, ticket, lead, appointments, courses, listings, services, invoice, order, payment, subscription, contract in beta, credit memo and custom objects. They do not work on products or quotes.

Three constraints shape the repair. First, create associations matches on property values only, and only on single-line text, multi-line text, phone number, number, single checkbox and single select properties. Second, those values are case sensitive and must match exactly, so a contact whose Company name reads hubspot will not match a company whose Name reads HubSpot. Normalising case and trailing whitespace is therefore part of the repair, not a tidy-up after it. Third, the action carries a daily limit of 5 million executions including failures, and applying a label counts as two executions rather than one.

The reversibility rule is the one to design around. Remove association labels can also remove every association carrying the selected label, but it cannot remove associations on records that have no label. So label the associations you create during a repair, even where the label adds nothing semantically, because an unlabelled association created in bulk can then only be removed through the index page or the API. When operating on records other than the enrolled one, the targeting options are all associated records, capped at the 100 most recently associated, most recently updated, most recently created, first created, most recently associated, first associated, or records carrying a specific label. That cap of 100 matters before trusting a workflow to touch a conglomerate account with hundreds of related records.

What structure stops it happening again?

Association limits, set per object pair and per label, because a limit the platform enforces outlasts a convention the team agrees to.

HubSpot's article on setting limits for record associations, last updated 1 September 2026, puts them in Data Management, then Data Model, then Edit Data Model and the graph view, where the line between two objects carries the limit. Each direction is set independently to many records or to a custom number up to 10,000, and most association labels default to one-to-many. Limits can also be set per label, so one contact labelled Billing contact per company becomes a constraint rather than a training point. Super Admin permissions are required, and once saved, users cannot create associations or labels that exceed the limit. Where a total limit and a label limit disagree, the total wins: if associated contacts are limited to one and the Decision maker label is set to many, the maximum is still one.

Sequence matters, because limits interact with the merge backlog. The merge documentation names exceeding configured association limits as a cause of merge failure, so limits set tightly before the duplicates are resolved will block the very merges that would resolve them. Close the creation paths first, merge second, tighten the limits third. The pattern across more than 30 engagements over the last seven years is that teams who hold that order get a durable result, while teams who start at the merge screen are back at the same counts within two quarters.

One thing this page leaves out is the structure you rebuild into. The data model question of one record against several is argued in our guide to CRM architecture for multi-product B2B sales, and the sequencing of a platform move in our CRM migration playbook. An audit tells you what you have and why, not what to build.

FAQ

Can you undo a merge in HubSpot?

No. HubSpot states that it is not possible to unmerge records. The partial recovery route is the additional email address or domain name that the merge preserved: delete it from the merged record and create a new record with that value, which gives you a record but not its history. Use the Merged [record] IDs property to see which Record IDs went into any given record, and hover the property value and click Details to see who performed the merge and when.

Why did my merge fail?

Four documented causes: the two records have been involved in a combined total of 250 or more merges, the result would exceed your configured association limits, the companies sit in a parent-child relationship containing a loop, or the account runs the old version of the HubSpot and Salesforce integration, which does not permit company merges.

Does merging contacts break my workflows?

It changes enrolment. Outside the Primary ID Preservation beta, both records are unenrolled from their active workflows at the point of merge. Inside the beta, the primary stays enrolled with its delays and branches intact and only the secondary is unenrolled. Either way, the result does not automatically enrol in new workflows because of merge-driven data changes unless you have allowed enrolment from merges in your workflow settings.

Why is the primary company association so important?

Because three systems read it and nothing else. Timeline activities associate automatically with only the primary company, the company lifecycle stage sync updates only the primary company's stage, and segments, workflows and cross-object reports reference the primary association. A contact on the right company but not as primary looks correct on the record and reports wrongly everywhere else.

Can I clean up duplicates without Data Hub?

Partly. Reviewing and merging contact and company duplicates individually comes with Marketing, Sales, Service, Data Hub or Smart CRM at Professional or Enterprise. Bulk merging, custom detection rules, the duplicate alerts table and the audit log of auto-merged records all require Data Hub. Merging two records you have already identified is available on all plans.