← All playbooks
Newsletter migration

Mailchimp → Customer.io

Export each Mailchimp audience by status, then import people into Customer.io with email as the identifier. Bring unsubscribes in before anyone can send, and rebuild journeys as campaigns.

Typical timeline4 to 7 days before the first real send8 to 14 hours active work
Statusneeds review
Source profileMailchimp audience export and suppression docs reviewed 2026-11-06
Destination profileCustomer.io CSV import, export, and unsubscribe docs reviewed 2026-11-06
Documentation date
Review window
Evidence5 sources
This route needs review.Use it as a planning baseline, then verify the dated sources and test with representative data before production.
Before you migrate

Should you make this move?

Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.

Current platform

Mailchimp

Reasons to stay
  • A broad small-business marketing suite combines email, contacts, forms, and campaigns
  • Audience, campaigns, automations, and reporting live in one publishing system
Reasons to leave
  • Pricing, interface complexity, and audience-based billing can become frustrating
  • Automation logic, analytics history, and deliverability settings are not very portable
New platform

Customer.io

What gets better
  • People, attributes, and events drive campaigns without a separate list for every segment
  • Audience, campaigns, automations, and reporting live in one publishing system
What gets worse
  • Journeys, Liquid, and event history have to be rebuilt, and a CSV import can fire automations while it runs
  • Automation logic, analytics history, and deliverability settings are not very portable
Best of the move

Customer.io: People, attributes, and events drive campaigns without a separate list for every segment. This removes a major source-side concern: Pricing, interface complexity, and audience-based billing can become frustrating.

Worst of the move

What you lose: A broad small-business marketing suite combines email, contacts, forms, and campaigns. What you inherit: Journeys, Liquid, and event history have to be rebuilt, and a CSV import can fire automations while it runs.

Jump to a section
01At a glance

Know the shape of the move.

Transfer outcome12 features audited
Transfer outcome distributionClean transfer: 0, Partial transfer: 2, Manual rebuild: 6, Not transferred: 4.
Clean0
Partial2
Manual6
Lost4
Mapping route8 of 9 fields have a destination path

This timeline assumes

  • One Mailchimp audience, under 100 columns of merge fields, and a CSV under 100 MB. Split larger files. Customer.io says an import takes about a minute per 20 to 30 thousand rows.
  • You own the Mailchimp account, the Customer.io workspace, and DNS for the sending domain.
  • Email is enabled as an identifier in the Customer.io workspace before the import.
  • The site already documents Mailchimp → Klaviyo and Mailchimp → Kit if a list-based tool is a better fit than an event-driven one.
  • No Customer.io campaign or broadcast sends to this audience until counts, unsubscribes, and a seed message pass.
02What transfers

What survives the move.

“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.

ItemOutcomeImpactWhat happensMitigation
Subscribed contactspartialcriticalMailchimp can export an audience as a ZIP with separate CSVs for subscribed, unsubscribed, non-subscribed, and cleaned contacts. Customer.io imports a CSV when a column maps to id, email, or phone. A column named email maps to the reserved email attribute.Import the subscribed file only after unsubscribes are in. Map Email Address to email. Record the Mailchimp count and the Customer.io import result.
Unsubscribes and cleaned addressespartialcriticalCustomer.io stores a global unsubscribed attribute. true means the person is unsubscribed from email, SMS, WhatsApp, and push. Mailchimp's cleaned contacts are hard bounces, not the same flag.Import unsubscribed people with unsubscribed set to true before any send. Keep cleaned addresses out of the subscribed file. Do not treat a cleaned row as a new subscriber.
Tags and groupsmanualhighMailchimp tags and groups are not Customer.io segments. Extra columns become attributes if you map them. Customer.io builds segments from attributes and events, not from a stored list membership.Map each tag you still use to a boolean attribute. Rebuild the segments you send to. Drop tags nobody references.
Customer journeyslostcriticalMailchimp automations do not import as Customer.io campaigns. A CSV row can trigger an automation while the import runs, because Customer.io processes imports row by row.Pause or draft every campaign that triggers on a new person or an attribute change. Rebuild journeys after the import, from the event you actually care about.
Campaign content and templatesmanualhighMailchimp templates do not become Customer.io designs. The drag-and-drop editor inserts an unsubscribe block with the Liquid tag for you. A hand-built message needs that link.Rebuild the next three campaigns. Confirm each message contains an unsubscribe link before it can send.
Open and click historylostmediumA Mailchimp contact export does not include open and click rates. Those live on email reports. Customer.io will not have that history on the person.Export any report you still need from Mailchimp and archive it. Do not expect a segment based on past opens to match.
Signup forms and landing pageslosthighMailchimp forms and pages do not move. New signups still land in Mailchimp until you point them at Customer.io.Replace each live form before cutover. Keep Mailchimp forms from accepting people after the freeze.
Sending domainmanualcriticalCustomer.io authenticates on an account-specific subdomain such as cio#####.yourdomain.com, so the records do not replace the root domain. You add MX, SPF, DKIM, and a DMARC check. Verification can take up to 72 hours. Unless you use your own SMTP, the domain must verify before Customer.io will send from it.Add the domain in Workspace Settings, publish the records Customer.io shows, and click Verify domain. Do not delete existing mail records on the root.
Multiple audiencesmanualhighMailchimp audiences are separate. Customer.io has one workspace of people. The same email in two audiences can collapse into one person, or error if you update by email and two people already share it.Pick one primary audience. Note which other audience a duplicate came from, as an attribute, before you merge.
Non-subscribed contactsmanualhighMailchimp's non-subscribed status is not a Customer.io concept. If unsubscribed is false or missing, Customer.io treats the person as subscribed, or as following topic preferences when a subscription center is on.Do not import non-subscribed rows as ordinary people unless you set unsubscribed true or you have consent to mail them.
E-commerce eventslostmediumMailchimp purchase events do not ride along in the contact CSV. Customer.io can import events from a separate CSV, with _cio_name and _cio_customer_id, but that is a second file you build.Leave historical orders out of the first import. Send new events from the store after cutover.
Export retentionmanualmediumMailchimp keeps contact exports in the account for 30 days. Customer.io deletes an export from the workspace after 60 days.Download both files and store them with checksums outside either account.
03Field and feature mapping

Where each thing goes.

SourceDestinationMethodNotes
Mailchimp Email AddressCustomer.io emailautomaticEnable email as an identifier. One email per cell.
Subscribed CSVPeople with unsubscribed falsetransformImport this file only after the unsubscribe file.
Unsubscribed CSVunsubscribed truetransformtrue also clears subscription-center topics.
Cleaned CSVNo destinationunsupportedKeep hard bounces out of the subscribed import.
Merge fields such as FNAME and LNAMEAttributestransformA new column title becomes a new attribute.
Tags and groupsBoolean attributes, then segmentsmanualThere is no list object to receive a Mailchimp audience.
Customer JourneyCampaignmanualRebuild the trigger. Do not leave the campaign live during import.
Audience export ZIPArchived CSVsmanualOnly Owners and Admins can export an audience.
Mailchimp sending domainCustomer.io sending domain on cio##### subdomainmanualAdd the four DNS records. Do not remove root mail records.
04Before you begin

Make the move recoverable.

Backup procedure

Create the source-of-truth backup

Keep a full Mailchimp audience export, campaign list, and DNS snapshot before Customer.io imports or sends.

  1. Export the audience. Unzip subscribed, unsubscribed, non-subscribed, and cleaned CSVs and record each row count.
  2. Export the email reports you still need. The contact CSV will not contain opens and clicks.
  3. List live journeys, signup forms, and the next scheduled campaign.
  4. Save the current DNS records for the sending domain.
  5. Store the files with checksums. Edit copies, not the originals.

Proof to capture: A dated note with CSV checksums, the four status counts, the journey list, and the DNS snapshot.

Transformation · Mailchimp audience export plus a spreadsheet

Split the Mailchimp ZIP by status

Stop cleaned and unsubscribed addresses from landing as mailable people.

  1. Download the ZIP from the export email. Mailchimp keeps it for 30 days.
  2. Count rows in each status file, minus the header.
  3. Add an unsubscribed column. Set true on the unsubscribed file and false on the subscribed file.
  4. Leave the cleaned file out of both imports.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

Transformation · Customer.io People, Add people, CSV

Import people into Customer.io

Create people by email without firing live campaigns.

  1. Pause campaigns that trigger on a new person or an attribute change.
  2. Import the unsubscribed file first. Map email and unsubscribed. Add new people. Ignore empty values.
  3. Import the subscribed file the same way.
  4. Read the import email. Customer.io cannot stop an import after you click Import.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

Transformation · Customer.io Workspace Settings, Email, and your DNS host

Authenticate the sending domain

Let Customer.io send from your domain without taking over root DNS.

  1. Add the domain and the From address.
  2. Publish the MX, SPF, DKIM, and DMARC records on the cio##### subdomain Customer.io shows. DMARC on the root is enough if one is already there.
  3. Click Verify domain. Wait, then verify again. This can take up to 72 hours.
  4. Do not delete the records that receive your own mail.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

05Handle with care

The things most likely to hurt.

These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.

Import

The import sends mail

criticallikely likelihood

Customer.io processes the CSV row by row, and a new person or attribute change can enter a campaign.

Consequence
The whole list gets a journey email during the import.
Mitigation
Pause those campaigns first. Import unsubscribes before subscribers.

Stop if: Any live campaign still triggers on person creation or on the attributes you are writing.

Consent

Unsubscribes arrive as subscribed

criticalpossible likelihood

A missing or false unsubscribed value means the person can be mailed.

Consequence
You mail people who opted out in Mailchimp.
Mitigation
Set unsubscribed true from the unsubscribed CSV. Sample both files after import.

Stop if: Any sampled opt-out is missing or has unsubscribed set to false.

Domain

Root DNS gets replaced

highpossible likelihood

Customer.io's records belong on its subdomain. The docs say not to delete your own domain's records.

Consequence
Your inbox stops receiving mail.
Mitigation
Add only the records on the cio##### hostnames. Keep a copy of the previous zone.

Stop if: A root MX or SPF record was edited and inbound mail fails.

People

Two Mailchimp audiences collapse

mediumpossible likelihood

Customer.io updates by email fail when two people already share that email.

Consequence
One audience's attributes overwrite the other, or rows error.
Mitigation
Import one audience, then review duplicate-email errors before the second.

Stop if: The import report shows duplicate-email errors you have not explained.

06Precise timeline

Do the work in this order.

Estimate forOne Mailchimp audience, CSV files under 100 MB and 100 columns, one sending domain
Total elapsed4 to 7 days before the first real send
Active work8 to 14 hours
BufferLeave up to 72 hours for domain verification, and another import pass if a file is over 100 MB.
01
Day 1Export the audience and list what sends1 day
02
Day 2Prepare Customer.io and the domain1 to 3 days
03
Day 3Import unsubscribes, then subscribers1 day
04
Day 4Rebuild segments and the next campaign1 day
05
Day 5Freeze Mailchimp and send once1 day
  1. Day 1 · inventory

    Export the audience and list what sends

    2 to 3 hours active1 day elapsedMailchimp export email waiting
    • Export the audience and count each status file.
    • List journeys, forms, and the next campaign.
    • Save DNS for the sending domain.
    Stop / go checkpoint

    Do the status counts add up?

    Go when: Subscribed, unsubscribed, non-subscribed, and cleaned counts match the audience.

    Stop when: An owner cannot export, or a status file is missing.

  2. Day 2 · workspace

    Prepare Customer.io and the domain

    2 hours active1 to 3 days elapsedUp to 72 hours for DNS verification waiting
    • Enable email as an identifier.
    • Add the sending domain and publish DNS.
    • Draft the campaigns you will rebuild. Leave them unable to send.

    Depends on: inventory

    Stop / go checkpoint

    Can this workspace receive people safely?

    Go when: Email is an identifier and no campaign will fire on import.

    Stop when: A live campaign still triggers on new people.

  3. Day 3 · import

    Import unsubscribes, then subscribers

    2 to 4 hours active1 day elapsedAbout a minute per 20 to 30 thousand rows waiting
    • Import unsubscribed people with unsubscribed true.
    • Import subscribed people with unsubscribed false.
    • Read both import results before you touch campaigns.

    Depends on: workspace

    Stop / go checkpoint

    Did both files land?

    Go when: Counts match, or each gap is an invalid email or a duplicate you logged.

    Stop when: Opt-outs are missing or a campaign sent during the import.

  4. Day 4 · rebuild

    Rebuild segments and the next campaign

    3 to 4 hours active1 day elapsedNone waiting
    • Turn the tags you still use into attributes and segments.
    • Rebuild the next message, including the unsubscribe link.
    • Send only to a seed list.

    Depends on: import

    Stop / go checkpoint

    Is the seed send clean?

    Go when: Seeds get one message, the unsubscribe link works, and Mailchimp sent nothing.

    Stop when: A seed is missing, duplicated, or an opt-out received mail.

  5. Day 5 · cutover

    Freeze Mailchimp and send once

    1 to 2 hours active1 day elapsedDomain verification if it is still pending waiting
    • Stop Mailchimp campaigns and forms.
    • Import the last status delta.
    • Send the first Customer.io campaign with one owner watching.

    Depends on: rebuild

    Stop / go checkpoint

    Which product sends the next campaign?

    Go when: The domain is verified, counts still match, and the seed passed.

    Stop when: Verification is incomplete or a Mailchimp campaign is still scheduled.

07The point of change

Cut over with a way back.

Go live

Cutover

Make Customer.io the only sender without mailing opt-outs or double-sending the list.

Recommended window: A weekday when the Mailchimp owner, the Customer.io owner, and the DNS owner are all around, at least a day before the next campaign.

  1. Pause Mailchimp campaigns and journeys. Record the time.
  2. Export once more and import only the new rows.
  3. Confirm the sending domain shows verified.
  4. Send the Customer.io campaign to the seed list, then to the segment.
  5. Leave Mailchimp unable to send until the next morning's counts still match.

Proof to capture: Freeze time, both import emails, domain verification, and the seed headers.

Return to safety

Rollback

Send the next campaign from Mailchimp if Customer.io consent or delivery is wrong.

Deadline: The clean point is before the first full Customer.io send. Keep Mailchimp readable for seven days after that send.

  1. Stop the Customer.io campaign and keep the import report.
  2. Do not delete people. You may need the unsubscribed flags to compare.
  3. Schedule the next send in Mailchimp only, from the pre-freeze audience.
  4. If new signups arrived in Customer.io, export them and add the consented ones in Mailchimp by hand.
  5. Leave the cio##### DNS records in place until mail is stable. Removing them is a separate change.

Proof to capture: Mailchimp is the only scheduled sender, and a sample of opt-outs stayed unsubscribed there.

Rollback immediately when
  • A known Mailchimp opt-out has unsubscribed set to false.
  • A campaign sent while the CSV was still importing.
  • The sending domain is still unverified when you meant to send.
  • Subscribed counts differ and you cannot name the missing rows.
08Verification report

Prove the migration worked.

Every blocking check must pass. Capture the evidence before cleanup begins.

0%
Interactive report preview0 / 8 checks passed
PassIDCheckMethodExpected resultEvidence
AUD-01BlockingStatus countsCompare Mailchimp subscribed and unsubscribed counts with Customer.io filters on unsubscribed.Counts match, or every gap is a logged invalid or duplicate email.Mailchimp export counts and the Customer.io import emails.
CON-01BlockingOpt-out samplePick 20 addresses from the unsubscribed CSV and open them in Customer.io.Each has unsubscribed true.The address list and screenshots of the attribute.
CLN-01BlockingCleaned addresses stayed outSearch Customer.io for 10 cleaned addresses.They are absent, or present only with unsubscribed true and a note.The search list.
SEG-01Tag attributesCompare one Mailchimp tag count with the boolean attribute.The counts match for every tag you still send to.The tag table.
CAM-01BlockingNothing fired on importOpen campaign metrics for the import window.No production campaign sent during the import.Campaign delivery timestamps.
DNS-01BlockingSending domainRead Verify domain and send a seed from the real From address.SPF, DKIM, and DMARC checks are green. The seed arrives signed.Verification screen and seed headers.
UNS-01BlockingLink in the messageOpen the seed and use the unsubscribe link on a test person.unsubscribed becomes true and a later test does not send to them.Before and after attribute values.
ONE-01BlockingOne senderLook at the Mailchimp campaign calendar and Customer.io scheduled sends.Only the named Customer.io campaign can send.Both schedules.
09Post-migration cleanup

Remove the scaffolding safely.

Safe after: One full Customer.io send, a day of normal bounces and complaints, and a signed count check.

  1. Archive the Mailchimp ZIP, both import reports, and the DNS snapshot outside either product.
  2. Turn off remaining Mailchimp journeys and forms.
  3. Remove Mailchimp users that only existed for the export.
  4. Keep the Mailchimp audience readable for the agreed retention window before you cancel.
  5. Write the next review date on the playbook.
Sources and evidence

Verify against the primary material.

Platform behavior changes. Check these sources and the review dates above before executing a production migration.

  1. Mailchimp: view or export contactsAccessed 2026-11-06
  2. Mailchimp: import a suppression listAccessed 2026-11-06
  3. Customer.io: import people or events via CSVAccessed 2026-11-06
  4. Customer.io: global unsubscribesAccessed 2026-11-06
  5. Customer.io: domain authenticationAccessed 2026-11-06