Here's the trap nobody warns you about when you leave Twilio: you can port the exact same phone number, keep the exact same customers, and still blast a text to someone who told you to stop six months ago. The number travels. The opt-out history doesn't.

Full disclosure: I work for Ready, and we obviously want you to migrate to us. But the thing I'm about to describe is true no matter where you go: Ready, a different CPaaS, your cousin's homegrown script. Carrier-level opt-outs and your application-level suppression list are two different things, and only one of them follows the number.

Why porting a number doesn't port the STOP list

When a contact texts STOP to a number running on Twilio, two things happen. Twilio's Advanced Opt-Out feature records the opt-out in your Twilio account, and in many setups the carrier also notes the suppression against that sending number. The carrier-level block is a courtesy layer, not a complete record, it's keyed to routing on Twilio's infrastructure, and it does not reliably transfer when you port the number to a new provider's platform.

The record that actually matters, "this specific person, on this list, revoked consent on this date", lives in your Twilio account database. It is not metadata attached to the phone number. Port the number, cancel the Twilio account, and that record is gone unless you exported it first.

So the failure mode is brutal and quiet: you go live on a new provider, upload your contact list from your CRM (which still contains the opted-out people, because your CRM and Twilio's opt-out table were never fully synced), and the new platform, having no history, happily sends to all of them. Every one of those sends to a person who said STOP is a potential TCPA violation at $500 to $1,500 per text.

This is the same silent-reset problem that happens to ecommerce subscriber consent, we wrote the long version in Switching SMS Platforms Can Silently Reset Your Subscribers' Consent Status. Opt-outs are the mirror image: instead of losing proof that people opted in, you lose proof that people opted out.

The three lists you have to move, not one

People think "my opt-out list" is a single thing. It's at least three, and they live in different places:

  1. Explicit STOP/UNSUBSCRIBE replies, contacts who texted a stop keyword. In Twilio, these are in your opt-out records and Messaging Service logs.
  2. Your internal do-not-contact list, people who asked you to stop by email, phone, or in person and were manually suppressed. This almost never lives in Twilio at all; it's in your CRM or a spreadsheet.
  3. Previously scrubbed numbers, litigators, DNC complainers, and line-type (landline) exclusions you already paid to filter out.

Lose any one of these in the move and you re-expose yourself. The internal list is the one teams forget most, and it's the one regulators look at first, we get into why in the internal vs. federal do-not-call breakdown.

The export: pulling your opt-out history out of Twilio before you cancel

Do this before you cancel Twilio, not after. Once the account closes, the data is unrecoverable.

1. Export opt-out records. Twilio stores opt-out state per Messaging Service. Use the Console or the API to pull the list of numbers that have opted out of each Messaging Service you've used. If you've run multiple services or campaigns, pull every one, opt-outs don't automatically cross between them inside Twilio either.

2. Export message logs filtered for inbound stop keywords. Belt and suspenders. Query your inbound message history for bodies matching STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, QUIT. The export gives you the number and the timestamp, which is the evidence you want if a specific opt-out is ever challenged.

3. Export your CRM suppression flags. Whatever field marks a contact as do-not-text, sms_opt_out, a tag, a status, export the full list of those contacts' phone numbers.

4. Normalize everything to E.164. +15551234567, no dashes, no parentheses, country code included. This is the single most common reason an import "succeeds" but half the suppressions don't actually match, formatting mismatches mean (555) 123-4567 and +15551234567 are treated as two different people.

Deduplicate across all four exports into one master suppression file with two columns at minimum: phone_e164 and opted_out_at. Keep the timestamp. That date is your audit trail.

The import: loading suppressions into the new platform first

The order of operations is the whole game. Import your suppression list before you import your active contact list. If you load active contacts first and send a campaign before the suppressions land, you've already fired.

On Ready, the sequence looks like this:

  • Register your brand and campaign (10DLC), this runs in parallel and typically clears in 1 to 3 days, often same-day. We broke down what compresses the timeline in Most A2P Onboarding Takes 2-4 Weeks.
  • Import the master suppression file so every one of those numbers is marked opted-out before any campaign exists to send to them.
  • Then import your active contacts.
  • From that point, Ready's automatic STOP/opt-out handling takes over for anything new: an inbound STOP is honored and the opt-out propagates across campaigns, so a contact who stops one message can't be reached through another. That's the mechanism that prevents you from rebuilding this exact problem six months from now.

One more thing most teams skip: opt-out rarely crosses channels. Someone who texted STOP can still be sitting in your power-dialer queue. If you're moving voice too, read A Contact Texts STOP but Keeps Getting Your Calls before you load your dial lists.

A worked example of what a reset actually costs

Say your Twilio account has 40,000 active contacts, and 2,100 of them have opted out over the years, a normal ~5% cumulative opt-out rate for a list that's been messaged for a while.

You port the number, skip the suppression export, and send a re-engagement blast to all 40,000. 2,100 of those texts go to people who revoked consent.

At the low end of TCPA exposure, that's 2,100 × $500 = $1,050,000 in theoretical liability from a single send. You won't get sued by all 2,100, but you only need a handful of them to be litigators to make it genuinely painful. And at least some of them are litigators, which is why a standalone litigator/DNC scrub at $0.005 per contact is cheap insurance on a freshly migrated list. Scrubbing all 40,000 would run $200. Compare that to one complaint. We did that comparison in full in Scrubbing 100,000 Contacts Costs $500: One TCPA Complaint Costs $500 to $1,500 Per Text.

Migration checklist

StepWhenWhy it matters
Export Twilio opt-out records (all Messaging Services)Before cancellingCarrier-level block doesn't port
Export inbound logs for STOP keywords + timestampsBefore cancellingTimestamps = audit trail
Export CRM suppression flagsBefore cancellingInternal DNC list isn't in Twilio
Normalize all numbers to E.164, dedupeBefore importFormat mismatches silently fail
Register 10DLC brand + campaignIn parallel (1 to 3 days)Unregistered traffic gets filtered
Import suppression listBefore active contactsPrevents sending to opted-out numbers
Import active contactsAfter suppressionsClean list, clean send
Re-scrub against litigator/DNCBefore first blastFreshly migrated lists rot, $0.005/contact
First campaignLastOnly after all of the above

The practical takeaway

Porting a number is a plumbing change. Preserving consent, both the opt-ins and the opt-outs, is a data migration, and it's entirely on you to do it right. The carrier and the old provider owe you nothing once the account closes.

Export your opt-out history before you touch the cancel button. Normalize it. Import suppressions first, contacts second, campaign last. Do that and the move is boring, which is exactly what a compliance migration should be.

If you're mapping out the full Twilio-to-Ready cutover, the migration playbook walks the rest of it (number porting, workflow triggers, and billing) and you can see current pricing here if you want to run your own numbers first.