One of the most confusing bugs in SFMC: the customer updated their email in the client's system, the nightly file import brought the new address into the Data Extension, but emails still go to the old address.
We've seen this on multiple engagements. Takes someone who's seen it before to diagnose in under an hour.
The two-list architecture
SFMC keeps email addresses in two independent places:
- Data Extension - the email column of whichever DE the send uses.
- All Subscribers List - the account-level master list, keyed by Subscriber Key.
When SFMC sends, and the subscriber's Subscriber Key already exists in the All Subscribers List, it uses the email from the All Subscribers List - not the email in the Data Extension.
So even if the DE has the new email, the All Subscribers List still holds the old one. SFMC follows the old one, email goes to the wrong address.
The mental model: think of the DE as a working copy and All Subscribers as the master register. The Send Engine never trusts the working copy when the master has an entry for that Subscriber Key - the master's value always wins.
Why it's designed this way
The All Subscribers List is SFMC's single source of truth for who a subscriber is at the account level. Subscribers can belong to multiple DEs and multiple sends, but their "identity" (Subscriber Key -> email) lives once in All Subscribers.
When you send from a DE, SFMC reconciles the DE rows against All Subscribers. If there's a conflict (different email for the same Subscriber Key), the All Subscribers version wins.
This is actually useful in normal operation - it prevents inconsistent email addresses drifting between multiple DEs. It's only surprising when you're trying to update the email.
Audit: how many wrong sends are queued up?
Before fixing the pipeline, find out the size of the existing problem. Run this SQL Query Activity against your sending DE joined to the _Subscribers data view to count subscribers whose DE email no longer matches the All Subscribers email:
SELECT de.SubscriberKey, de.EmailAddress AS DE_Email, sub.EmailAddress AS AllSubscribers_Email FROM [Your_Sending_DE] de INNER JOIN _Subscribers sub ON de.SubscriberKey = sub.SubscriberKey WHERE de.EmailAddress <> sub.EmailAddress
Each row in the result is a subscriber currently set up to receive sends at the wrong address. If the count is high, that's also the size of the silent goodwill loss already running through your account.
Save the result into a sync DE (call it Subscriber_Email_Sync) - it's the input for the fix below.
The fix: update the All Subscribers List too
Updating the DE alone isn't enough. You also need to push the email change into the All Subscribers List. Three methods, in order of how we usually deploy them:
Method 1: Scheduled sync via Import Activity
For ongoing pipelines, build an Automation that pushes the audit DE into All Subscribers:
Schedule (daily or hourly, after the upstream DE refresh) -> SQL Query Activity (the audit query above, output to Subscriber_Email_Sync DE) -> Import File Activity (target: All Subscribers List, NOT a DE) (update type: Add and Update) (key: Subscriber Key) (fields: SubscriberKey, EmailAddress)
The Import Activity targeting All Subscribers is the critical part. By default the destination picker drops you into a DE - you have to switch to All Subscribers explicitly at step 1 of the activity setup. This is the single click most teams miss the first time and then spend an hour wondering why the email column never updates.
Method 2: Direct UI import for one-off fixes
If you just need to fix a single batch of stale records (not set up an ongoing pipeline), use the Import Subscriber Wizard from Email Studio > Subscribers > All Subscribers > Import. Upload a file with Subscriber Key + EmailAddress. Update type: Add and Update.
The wizard does the same thing as the Import Activity - this method just skips the Automation Studio plumbing for ad-hoc cleanups.
Method 3: AMPscript UpsertContacts for real-time
For real-time updates from a Cloud Page, API call, or Journey Custom Activity, AMPscript has UpsertContacts() that pushes into the All Subscribers side directly:
%%[ var @rows set @rows = CreateArray() set @row = CreateObject("Property") SetObjectProperty(@row, "ContactKey", @subscriberKey) SetObjectProperty(@row, "EmailAddress", @newEmail) Add(@rows, @row) UpsertContacts(@rows) ]%%
Use this when DE updates are too slow for the use case (e.g. a customer changes email on a self-service portal and immediately triggers a confirmation email).
What about brand new subscribers?
If a Subscriber Key doesn't yet exist in the All Subscribers List, SFMC auto-creates the record using the email from the DE on the first send. No override problem because there's nothing to override.
The bug only appears when the Subscriber Key already exists with an old email value - which is also why it tends to surface late. Things look fine for weeks while the audience is mostly first-send subscribers, until enough customers update their email and a few of them complain.
Diagnosing it on a live ticket
When marketing ops files a "customer reports wrong address" ticket, the first place to check is All Subscribers - not the DE. Order of operations:
- Query the DE for that Subscriber Key. Confirm DE has the new email.
- Open Subscribers > All Subscribers in Email Studio, search for the Subscriber Key. Read the email value stored there.
- If DE has new email but All Subscribers has old, you've found it.
- Test: edit the All Subscribers record manually (it's editable in the UI), do a test send. If it goes to the new address, diagnosis confirmed.
The screenshot shows the All Subscribers panel with the Subscriber Key column visible — this is the table you read against, not the DE, when diagnosing wrong-address tickets.
This is the single shift that saves teams about a day per case - skip debugging the DE, skip the import logs, go straight to All Subscribers.
Prevention on new engagements
Include an All Subscribers sync in the data pipeline design from day one. Whenever customer email updates flow into SFMC, they should update both the relevant DE(s) and the All Subscribers List. A separate Import Activity targeting All Subscribers runs alongside the DE import, on the same schedule.
Document this in the runbook so it doesn't get dropped when someone new picks up the engagement. We add it to every SFMC handover doc precisely because it's the kind of thing that takes a fresh engineer a full day to rediscover otherwise.
Takeaway
The DE is not the source of truth for email addresses - the All Subscribers List is. Update both when email addresses change. Build the sync into the data pipeline from day one, not as a patch after the first angry client call.
Shipping an SFMC subscriber management pipeline? Our Salesforce team sets up All Subscribers sync, Contact Builder attributes, and identity resolution on production engagements. Get in touch ->
See our full platform services for the stack we cover.
Top comments (0)