Merging Two Customer.io Profiles Can Silently Resubscribe Someone Who Opted Out. There's Now a Setting to Stop It
Health information management has a word for the moment two people become one file. It calls it an overlay. AHIMA's white paper on duplicate records defines it as what happens when "the incorrect patient is registered, admitted, or documented on another patient's record", and the example it gives is almost too neat. A database merges John Clark, born 10/5/81, with a different John Clark, born 5/10/81. Two people, transposed digits, one commingled record.
What makes an overlay dangerous isn't the mess. It's what stops being reliably attached. AHIMA lists the parts of a record that can come loose after a matching error: diagnoses, testing, allergies, medications, contact details, family history, advance directives. ECRI, one of the larger patient-safety organisations, has been cited in a letter to Congress for naming patient identification among the top ten threats to patient safety.
Your marketing database is not a hospital, and nobody is going to be harmed by a bad merge in Customer.io. But your database does hold one flag with legal weight behind it, and deduplicating profiles is exactly the sort of routine admin that can drop it. Someone unsubscribed. You merged their duplicate. They're subscribed again.
Customer.io shipped a workspace setting on 21 July 2026 called Preserve unsubscribes on merge. This post covers what the default merge behaviour does to an opt-out and what the new setting fixes. Then the three merge paths you need to check separately, and the channels that will still message an unsubscribed person either way.
What a merge actually does in Customer.io
A merge keeps one profile and destroys the other. You nominate a primary profile and a secondary profile; the Customer.io documentation is blunt about the consequences: "The primary profile remains after the merge and the secondary is deleted. This process is permanent: you cannot recover the secondary profile."
There is no undo and no abort. The docs state that you "cannot undo a merge, nor can you stop it after it starts".
The primary doesn't come out unchanged, though. It inherits a lot from the profile you deleted: attributes it didn't already have, event history, automation journeys the secondary had started or completed, manual segment memberships, delivery history, conversions and relationships. The last 29 days of events land immediately and older ones can take up to an hour. One useful guard rail sits in that list: inherited events can't trigger automations, so a merge won't fire an event-triggered campaign. It can still drop someone into a segment-triggered one.
That inheritance is the whole point of merging. It's also why a merge deserves more thought than a bulk edit.
Where consent leaks: a subscribed primary beats an unsubscribed secondary
When both profiles hold a value for the same thing, Customer.io picks a winner, and by default the winner is the primary. For ordinary attributes the rule is primary-wins-unless-empty: if the primary's value isn't empty, it stays and the secondary's is lost.
Subscription preferences follow the same logic, which is where consent starts leaking. Straight from the docs: "The subscription topic preferences of the primary profile 'win' over the secondary profile. These preferences remain on the merged profile and the secondary profile's preferences are lost."
The worked example Customer.io gives is the one to sit with. You have a topic called Product Education. It's TRUE on the primary and FALSE on the secondary. After the merge, the value is TRUE.
Read that as a person rather than a boolean. One record says "yes, email me about this". The other says "no, stop". You merged them, and yes won because of which record happened to be primary. The release note describes the old default without any spin: "the primary profile's settings take precedence over the secondary profile's settings."
Nobody chose that outcome. Which is what makes it worth checking, because a duplicate marked unsubscribed is a common shape. The person unsubscribed from a work address, signed up later from a personal one, and your CDP eventually spots that they're the same human. Or someone unsubscribed years ago, a sales import re-added them under a different identifier, and a data-hygiene sprint reunites the two records. The unsubscribe is a signal worth reading, not just a boolean to store—and the merge quietly overwrites it.
The fix: turn on Preserve unsubscribes on merge
Go to Workspace settings > Merge options and enable Preserve unsubscribes on merge. That's it for the mechanics. The behaviour it swaps in is described in the docs as preserving "the most restrictive preferences across both the primary and secondary profiles".
Most restrictive means what it sounds like: "If either profile explicitly unsubscribed (globally or from a topic/channel), the merged profile is unsubscribed."
Three kinds of opt-out are covered, and it's worth naming them separately because they're stored differently.
Global unsubscribe lives on a boolean profile attribute called unsubscribed. Setting it to true opts the person out of Customer.io's native unsubscribe channels, and the subscription options overview lists those as email, SMS, WhatsApp and push.
Topic preferences control what kind of content someone gets—Product Updates, Marketing Offers—and only exist once you've enabled a subscription centre in the workspace.
Channel preferences control how they hear from you, so someone can keep your email and mute your SMS. Both topics and channels live in a JSON object on the profile called cio_subscription_preferences, where topics are keyed by numeric ID and per-channel opt-outs are keyed by channel type name.
The docs' second example shows how uncompromising "most restrictive" is. One profile is unsubscribed from Promotions and subscribed to Product updates. The other is the exact reverse. Merge them with the setting on and the result is unsubscribed from both topics.
Some teams will read that and wince at the subscribers they'll lose. Look at it the other way round: every one of those opt-outs is something a real person actually clicked. The setting doesn't invent restrictions, it just stops a merge discarding half of them.
What the setting does not cover
The protection is scoped to subscription preferences. Everything else still resolves the old way, primary wins if it isn't empty, and the release note and docs both keep the change deliberately narrow.
That matters more than it sounds if you track consent outside Customer.io's native fields. Plenty of teams keep their own audit trail—consent_source, consent_timestamp, lawful_basis, a marketing_ok flag inherited from an old CRM. Those are ordinary profile attributes. In a merge they resolve by which profile happened to be primary, unless the primary's value is empty, rather than by which value is true. Nothing in the docs suggests the setting reaches past subscription preferences, so assume it won't touch them.
So if your defensible record of consent lives in custom attributes, the new setting protects the sending behaviour and leaves your paperwork to chance. Worth knowing before an audit rather than during one.
Audit your three merge paths
Customer.io documents three ways profiles get merged: manually, automatically, and through the Track API. Check them one at a time, then check how you'd spot a bad merge after the fact.
Manual and automatic merges are covered
The scope sentence in the docs is short: "This setting applies to both automatic and manual merges."
Manual is the Merge button on the Profiles page, where you pick the primary and secondary yourself. Automatic covers two workspace settings that do it without you:
- Multi-identifier profile merge joins two profiles when an
identifycall arrives carrying identifiers that belong to different records. Each identifier has to match exactly one profile, and the two records must be complementary—each missing the value the other holds, with no conflicts elsewhere. - Auto-merge on update extends that to the case where an
identifycall tries to change an identifier to a value another profile already owns. Without it, Customer.io drops the change and logs a Failed Attribute Change.
Automatic merges are the ones to think hardest about, because nobody reviews them. When Customer.io merges automatically it picks the primary by age: "the older profile is the Primary and the younger profile is the secondary." Nothing in that rule knows anything about consent. If your older record is the subscribed one, the default merge behaviour discards the newer opt-out every time.
This is also where a CDP sending identify calls becomes part of your consent surface rather than just your data plumbing. Every identify call that stitches two identities together is a potential merge, running at pipeline volume. Two more things the docs are clear about: auto-merges are permanent, and turning the settings on doesn't backfill, so existing duplicates stay put until you deal with them.
The Track API merge call isn't named
Here's the gap. Customer.io also lets you merge with a POST to https://track.customer.io/api/v1/merge_customers, documented on the same page as manual and automatic merges. The sentence defining the new setting's scope names automatic and manual merges only. The API isn't mentioned.
I went looking for a clearer answer and didn't find one. The Track API reference describes merge_customers in terms of combining attributes and keeping the primary's identifier, with nothing about subscription preferences, and the OpenAPI spec behind that reference is silent on the point too.
That silence is probably just docs being docs. An API merge and a UI merge almost certainly run the same code path, and it would be odd for a consent safeguard to skip one. But "almost certainly" isn't a control. If your deduplication runs through the API—a nightly script, an ops tool, a bulk cleanup—test it before you trust it. Create two throwaway profiles in a test workspace, unsubscribe the one you'll make secondary, merge them by API, and read the merged profile's subscription preferences. Then ask support to confirm in writing. That's ten minutes for an answer you can put in front of a DPO.
How to see which merges touched consent
Three places show you merges after the fact.
Profile activity records a Profiles merged entry on the surviving profile, and the Source field tells you how it happened: the Profiles page, the API, or automatically. That's the fastest way to check a specific complaint.
The profile_merge event is the programmatic version. Customer.io names it as the way to monitor merges alongside profile activity, so it's the hook for reporting or alerting on merge volume.
The workspace audit log carries a Profile Merge activity under Profiles & Objects, described as "Merging of duplicate customer profiles". Two caveats. Access needs Account Admin, and retention depends on your plan, per the audit log docs. Essentials gets 30 days of view, filter and export. Premium and Enterprise can filter over any period and export up to a year. If you're on Essentials and someone complains about an email from four months ago, the log may not go back far enough to tell you why.
The channel caveat: some messages ignore a preserved opt-out
Preserving the unsubscribe is not the same as never sending. Whether an opt-out is honoured depends on the channel, and the subscription overview documents the split:
| Channel | Subscription behaviour |
|---|---|
| Email, SMS, push, WhatsApp | Respects global unsubscribe, topic preferences and channel preferences |
| In-app | Ignores global unsubscribe and topic preferences by default; respects channel preferences if you configure in_app as a channel |
| Slack | Ignores global unsubscribe and topic preferences; respects channel preferences if you configure slack as a channel |
| Webhooks | Bypasses all subscription checks |
So a globally unsubscribed person is still eligible for in-app messages and Slack messages, and webhooks don't consult subscription state at all. The docs' own flowchart puts it plainly: once unsubscribed is true, the person "is only eligible for in-app or Slack messages".
You can at least give those surfaces something to respect. Add in_app and slack as channels in your subscription centre and people can opt out of them explicitly, which the preserve-unsubscribes setting then protects like any other channel preference. What that won't do is make an existing global unsubscribe apply to in-app or Slack. That gap stays open, and webhooks sit outside subscription checks entirely. Whether the extra channels are right for you depends on what you send in-app. Product education, probably yes. A billing warning, probably not.
One more layer that catches people out: topics and channels combine as an AND. Someone must be subscribed to both the topic and the channel to receive a message, so an opt-out at either level blocks the send.
Why this is a compliance control, not a preference
The regulator's position leaves no room to treat a resubscribe as a data-quality footnote. The ICO's guidance on respecting people's preferences, updated 28 April 2026, is direct: if someone uses the unsubscribe link in your email, "you must not send them any further marketing emails". On objections it's firmer still—"There are no reasons that you can use to refuse their objection."
One line in that guidance does the real work here. The ICO notes that a person's most recent indication of their wishes is what counts. Then it adds the qualifier: "failing to opt out of your direct marketing at a later date doesn't override their previous objection." A merge is not the person changing their mind. It's your database changing its mind on their behalf, which is a different thing entirely.
The same guidance is why suppression beats deletion. The ICO says you "should" keep a suppression list "instead of just deleting their details", keeping only the minimum needed to honour the preference. In Customer.io that's the reason an erasure request needs delete and suppress rather than delete alone, and it puts merge hygiene in the same family as deciding what not to send.
Then there's the deliverability bill. People who opted out and got mail anyway are among your most likely spam complainers. Gmail's sender guidelines ask senders to keep spam rates in Postmaster Tools "below 0.10% and avoid ever reaching a spam rate of 0.30% or higher". That's one complaint per thousand messages delivered, so the working ceiling doesn't leave much room. A few hundred silently resubscribed people can move that number on a single broadcast.
The audit, in order
- Turn on Preserve unsubscribes on merge in Workspace settings > Merge options. Nothing else on this list matters until that's done.
- Check whether Multi-identifier profile merge and Auto-merge on update are enabled, and whether a CDP or reverse-ETL job is sending identify calls that trigger them.
- Test an API merge in a test workspace if your deduplication runs through
merge_customers, and get support's answer in writing. - Decide whether
in_appandslackshould exist as channels in your subscription centre, so those surfaces respect a channel opt-out. - Check whether your consent audit trail lives in custom attributes. A merge resolves those by primary-wins, so make sure the native subscription fields carry the same state—those are the ones the setting protects.
- Filter the workspace audit log for Profile Merge and see how many merges happened in the last 30 days. If the answer surprises you, that's the finding.
Deduplication is worth doing. Merging profiles fixes fragmented histories, broken personalisation and duplicated sends. Just don't let it be the process that decides who has consented, because that's the one field where being wrong isn't a data-quality problem. If you'd like a second pair of eyes on your merge and consent setup, that's the sort of audit we run. Send us the details and we'll have a look.
Frequently asked questions
Does merging profiles in Customer.io resubscribe someone who unsubscribed?
It can, and by default it will. Customer.io's docs state that the primary profile's subscription topic preferences win over the secondary profile's, so if a subscribed primary absorbs an unsubscribed secondary, the merged profile comes out subscribed. Turning on Preserve unsubscribes on merge changes that, keeping the most restrictive state across both profiles instead.
Which profile wins when you merge duplicates in Customer.io?
The primary wins, in almost every case. For ordinary attributes, the primary's value stays unless it's empty, in which case it inherits the secondary's. Subscription preferences, relationship attributes and active automation journeys all resolve to the primary as well. The primary profile survives the merge and the secondary is deleted.
What does "Preserve unsubscribes on merge" actually do?
It replaces primary-wins with most-restrictive-wins for subscription preferences. The docs put it this way: if either profile explicitly unsubscribed, globally or from a topic or channel, the merged profile is unsubscribed. Where two profiles have opted out of different topics, the merged profile ends up opted out of both.
Where do I find the Preserve unsubscribes on merge setting?
It's in Workspace settings > Merge options, the same panel that holds the Multi-identifier profile merge and Auto-merge on update toggles. The setting is per workspace, so a multi-workspace account needs it enabled in each one.
Does it protect global unsubscribes as well as topic and channel preferences?
Yes. The docs cover all three explicitly: a global unsubscribe, a topic opt-out, or a channel opt-out on either profile carries through to the merged profile. Global status is stored on the unsubscribed profile attribute; topic and channel preferences live in a JSON object called cio_subscription_preferences.
Does the setting apply to automatic and CDP-driven merges?
Yes. The docs say the setting applies to both automatic and manual merges. That covers Multi-identifier profile merge and Auto-merge on update, the two settings that merge profiles when an identify call arrives with identifiers belonging to different records. Since a CDP or reverse-ETL job drives merges through those same identify calls, they're covered too.
Does it apply to the Track API merge_customers endpoint?
The docs don't say, so test it rather than assume. The sentence defining the setting's scope names automatic and manual merges only, and neither the Track API reference nor its OpenAPI spec mentions subscription preferences in the merge definition. If your deduplication runs through the API, merge two test profiles with a known opt-out on the secondary and read the result, then ask Customer.io support to confirm the behaviour in writing.
Does turning it on change how non-subscription attributes are merged?
No. The setting is scoped to subscription preferences. Every other attribute conflict still resolves primary-wins-if-not-empty, so custom fields you use to record consent, such as a consent_source or lawful_basis attribute, are decided by which profile was primary rather than which value is correct.
Can I undo a merge that resubscribed someone?
You can't. The docs state you cannot undo a merge, nor stop it once it starts, and the secondary profile can't be recovered. If a merge has overwritten an opt-out, the only remedy is to put the opt-out back yourself. Set the subscription preferences to the restrictive state, and suppress the person if the original request was an erasure or objection.
Does enabling the setting fix merges that already happened?
Not retroactively. It governs how future merges resolve, and past merges are permanent, so the current state of those profiles is what you have to work with. If you suspect historical merges overwrote opt-outs, the audit log's Profile Merge entries are the place to start, within your plan's retention window.
How do I find merges that touched someone's consent state?
Start with the profile: profile activity shows a Profiles merged entry on the surviving record, and its Source field tells you whether the merge came from the Profiles page, the API or an automatic rule. For workspace-wide reporting, the profile_merge event is the programmatic hook, and the workspace audit log lists Profile Merge under Profiles & Objects. Audit log access needs Account Admin, and retention runs to 30 days on Essentials.
Will turning this on stop every message to someone who opted out?
No, and this is the part most people miss. Email, SMS, push and WhatsApp respect global, topic and channel preferences. In-app and Slack messages ignore global unsubscribes and topic preferences by default, and webhooks bypass subscription checks entirely. Adding in_app and slack as channels in your subscription centre gives those surfaces a preference to honour.
Do I need a subscription centre for this to matter?
It matters either way. Topic preferences only exist once a subscription centre is enabled, but the global unsubscribed attribute works with or without one, and the setting protects global unsubscribes too. Workspaces running plain global unsubscribe are exposed to exactly the same failure mode: a subscribed primary overwriting an unsubscribed secondary.
Sources
- Resolve duplicate profiles. Customer.io Docs, updated 21 July 2026.
- Preserve unsubscribe preferences when merging profiles. Customer.io Docs, released 21 July 2026.
- Overview of subscription options. Customer.io Docs, updated 15 July 2026.
- Audit logs. Customer.io Docs, updated 15 July 2026.
- Respect people's preferences. Information Commissioner's Office, 28 April 2026.
- Email sender guidelines. Google, Gmail Help. Requirements effective 1 February 2024.
- A Realistic Approach to Achieving a 1% Duplicate Record Error Rate. American Health Information Management Association.
- ECRI Data Help Reignite Support for Patient Identifier in Congress. ECRI.
Want this working in your Customer.io workspace?
It's what we do all day for SMBs—strategy, automations, deliverability and hands-on execution.
See how we work as a Customer.io agency →

