E-commerce
Shopify subscription migration: the audit we run first
Before swapping Recharge or Bold for Shopify's native selling plans, run this audit. The data model, webhooks, and payment vault decide whether the project is two weeks or two quarters.

A DTC coffee brand walked through our door last quarter paying $2,400 a month to Recharge. Their subscriber base was 4,100. The owner did the math on a Wednesday, opened Shopify's native selling plans documentation, and emailed us with one line: "how hard can this be."
The honest answer is: it depends entirely on what the audit finds. We have walked into Shopify Plus stores where the migration took eleven working days. We have also walked into stores where, after two weeks of audit work, we recommended the merchant stay on the third-party app for another year. The cost of getting that decision wrong is six figures of churned subscribers.
This is the checklist we run before we agree to take the project.
The five questions the audit has to answer
Every audit answers the same five questions. Skip any of them and the migration will surface the gap during cutover weekend, when the customer-success inbox is already on fire.
- Can every active subscription be reconstructed inside Shopify's data model?
- Will every active payment method survive the move?
- What downstream systems will break when the source-of-truth changes?
- What customer-facing features are powered by the old app and have no native equivalent?
- What is the rollback path if the cutover fails?
We work through each in turn. The audit deliverable is a single document, usually 12 to 20 pages, that answers each question with evidence pulled from the live store. No estimates, no "should be fine," no verbal handshakes.
Subscription contracts and the selling plan data model
Shopify's selling plans API is the destination. It models four things: a selling plan group, a selling plan, a subscription contract, and a billing attempt. Any subscription that exists in Recharge, Bold, Skio, or Loop has to fit into that shape.
Three patterns break the fit, and we look for all of them on day one.
The first is "swap any product." Some merchants let a subscriber replace next month's box with anything in the catalog. Shopify's contract is tied to specific variants. You can rebuild the swap flow with custom code, but it is a build, not a migration.
The second is dynamic pricing. If the subscription price changes per cycle based on the customer's loyalty tier, region, or a coupon they redeemed nine months ago, that logic lives in the third-party app's database. Selling plans support fixed amounts and fixed percentages off, plus a price change after N cycles. Anything else is custom.
The third is the prepaid plan. A 12-month prepay with monthly fulfillment is supported natively, but the accounting treatment of the unearned revenue often lives in a finance integration that does not know how to read Shopify subscription contracts yet. We check the GL mapping before we promise a date.
# Run this against the destination store to confirm the model fits.
query sellingPlanGroupShape($id: ID!) {
sellingPlanGroup(id: $id) {
name
appId
sellingPlans(first: 50) {
edges {
node {
name
billingPolicy {
... on SellingPlanRecurringBillingPolicy {
interval
intervalCount
}
}
pricingPolicies {
... on SellingPlanFixedPricingPolicy {
adjustmentType
adjustmentValue {
... on MoneyV2 { amount currencyCode }
}
}
}
}
}
}
}
}
The payment vault question
This is the question that kills migrations.
If the existing app uses Shopify Payments as the gateway, the saved payment methods are vaulted inside Shopify already. The migration moves the contract pointer, the card stays put. Clean.
If the existing app uses Stripe directly under its own platform account, the cards are in a Stripe vault owned by the app vendor, not the merchant. Moving those cards requires a PCI-DSS Level 1 vault-to-vault transfer between Stripe accounts, initiated by the source platform's compliance team. We have done this. It takes four to six weeks of paperwork, the source vendor has to agree, and at the end every customer in the EU still has to clear a fresh SCA challenge on their next billing attempt.
If the vendor refuses the transfer, the merchant has two options: re-collect payment methods through an email campaign and accept the churn, or stay on the vendor. We have seen the email-campaign route recover anywhere from 62% to 89% of subscribers depending on how the merchant framed it. Plan for the loss, then decide.
Payment-rail migrations are about contracts and vault custody, not about which provider has the nicer dashboard. The merchant who skips this question pays the bill on cutover Saturday.
If the answer to "who owns the card vault" is the app vendor, schedule the migration around a six-week PCI transfer or write off the cards you cannot recover. There is no third option.
Webhook surface and the downstream systems
Open the Shopify admin, go to Settings, Notifications, Webhooks, and write down every URL that receives subscription_contracts/*, subscription_billing_attempts/*, or orders/* events from the third-party app. Then ask the merchant: which of these do you know about? In our experience, the answer is roughly half.
The other half is Klaviyo flows, the warehouse's order-routing webhook, a finance Zap that posts to QuickBooks, a churn-prediction model someone built two years ago and forgot, and a Slack notifier that tells the founder when a high-LTV customer skips. Each one of these listens for a specific event shape from the source app. Shopify's native subscription webhooks do not have the same shape.
The third-party app's webhook payload often includes derived fields, next charge date, churn risk score, lifetime value, that Shopify's native webhook does not emit. Every consumer of those fields needs a rewrite or a translation layer before cutover.
We catalogue every consumer, classify it as "owned by us / owned by another team / owned by nobody," and tag the ones that need rewriting. The "owned by nobody" pile is where the post-launch fires come from. We have seen a single forgotten Zap, written by a freelancer in 2022, take down a merchant's accounting reconciliation for two weeks after a cutover.
The storefront surface
Two specific places to inspect.
The product detail page. The third-party app injects a widget that renders the subscribe-and-save toggle, the cadence selector, and any "first order discount" copy. That widget is usually built with the app's SDK and a script tag. After migration, it has to be rebuilt with Shopify's native subscription block or with a custom UI extension. The Liquid template that wraps it will reference variables that no longer exist. Every theme section that displays a subscription badge, a savings line, or a cadence selector goes on the audit list with a screenshot.
The customer account page. This is the bigger lift. Customers manage their subscription, skip, swap, change cadence, update card, inside the app's hosted portal. Shopify's new customer accounts have native subscription management, but it covers the basics. Any merchant-specific feature, a "gift this box to a friend" button, a "pause for the summer" flow, a referral credit applied at the next renewal, has to be rebuilt as a customer account UI extension or a custom app embed.
The audit lists every customer-facing surface the third-party app touches, with a screenshot of each one. The merchant signs off on the visual diff before we quote.
The rollback plan
The cutover is not a single transaction. It is a sequence: pause new sign-ups on the old app, export contracts, import contracts to Shopify, point webhooks, drain the old app's billing queue for the day's failed retries, switch the storefront widget. Each step has a rollback.
The audit defines, in writing, what triggers a rollback and who has authority to call it. "Failed billing attempts exceed 4% of expected daily volume for two consecutive cycles" is a trigger. "The founder feels nervous on Saturday morning" is not. The clearer this document is, the calmer the weekend.
A note on timing
Do not start the audit in the same quarter as the merchant's peak season. We have done this once and will not do it again. The audit needs interviews with the operations lead, the finance lead, and whoever owns the email program, and during a Q4 they are all unavailable. Run the audit in January or February for a spring cutover, or in June for an autumn cutover. The calendar is the cheapest variable to control. Spend it.
What you can do today
If you run a Plus store on a third-party subscription app and you are considering the move, open a single document and answer this: list every customer-facing feature the third-party app provides, with the URL of the page where it appears. If the list takes you more than fifteen minutes, the migration is not a two-week project, and the audit is worth doing before anyone signs a statement of work.
When we ran this audit for a Plus merchant in Rotterdam last spring, the thing we did not expect was that the app's "swap any product" feature was used by 0.4% of subscribers and yet was the single biggest blocker. We solved it by building a custom subscription portal on top of the native API and shipping the swap flow as a one-off account extension. If you want the kind of custom development that fills the gaps Shopify's native API does not yet cover, that is the work we do.
Key takeaway
The payment vault decides whether a Shopify subscription migration is two weeks or two quarters. Audit the gateway before you audit anything else.
FAQ
How long does a Shopify subscription migration take?
Anywhere from two weeks to two quarters, depending on payment-vault custody, the number of custom features built on the old app, and how many downstream systems consume its webhooks. The audit produces the real estimate.
Can we keep subscribers' saved cards when migrating off Recharge or Bold?
Only if the cards are vaulted inside Shopify Payments. If the third-party app vaulted them in its own Stripe account, you need a vault-to-vault transfer with the vendor's cooperation, which takes four to six weeks of paperwork.
Does Shopify's native subscription API cover everything Recharge or Bold can do?
It covers cadence, fixed discounts, prepaid plans, and basic skip plus swap of the same variant. Dynamic pricing, swap-any-product, rich pause flows, and gifting need custom code on top of the API.
What is the single highest-risk part of the migration?
The payment vault. If the source app owns the Stripe vault and refuses or delays the transfer, you either lose the cards or postpone cutover by months. Resolve the vault question before anything else.