Application Handover After a Stripe Subscription Migration
Last updated:
Direct answer: A Stripe subscription migration is not complete when destination subscriptions exist. The buyer’s application must use the destination account’s credentials and object IDs, verify webhook signatures with new endpoint secrets, map entitlements to the recreated subscriptions, and monitor the first renewals while the source account is deactivated according to plan.
Treat billing-object migration and application cutover as two linked workstreams with one reconciliation gate.
What Changes Across Stripe Accounts
| Item | Expected handover |
|---|---|
| Subscription ID | New destination ID; update local references using the migration ID map |
| Customer ID | Stripe currently says copied Customers keep their IDs, but reconcile the actual copy/export rather than assuming |
| Product and Price IDs | Destination-account IDs; update configuration, lookup tables, and admin tooling |
| Coupon and Tax IDs | Destination-account IDs where used |
| Publishable key | Replace in the client environment for the destination account |
| Server API key | Replace in the server secret store; never expose it to the client |
| Webhook endpoint ID | New when recreated in the destination account |
| Webhook signing secret | New endpoint secret; deploy it before accepting destination events |
| Customer Portal configuration | Destination-account configuration and links |
| Invoices, events, and logs | Historical objects remain in the source account |
MoveMRR provides downloadable old-to-new ID results for migrated objects. The application team remains responsible for applying them to its own database and configuration.
Phase 1: Inventory the Billing Contract
Before cutover, document every place the application depends on Stripe:
- environment variables and secret-manager entries;
- source-account Customer, Subscription, Product, Price, Coupon, and webhook IDs stored in the database;
- webhook event types and API version;
- entitlement or feature-access logic;
- checkout and Customer Portal links;
- dunning emails and payment-update routes;
- analytics, data warehouse, revenue recognition, tax, and support integrations;
- scheduled jobs that query Stripe;
- Connect or organization account context, if present.
Search both code and operational tools. A migration can bill correctly while the product still revokes access because an internal job is querying the old account.
Phase 2: Build and Validate the ID Map
Use a durable table rather than replacing IDs ad hoc:
| Local entity | Source Stripe ID | Destination Stripe ID | Verified state | Cutover owner |
|---|---|---|---|---|
| Customer or tenant | cus_… | Actual copied destination ID | Default method checked | Billing |
| Subscription | sub_… | New sub_… | Status and next billing date checked | Engineering |
| Price | price_… | New or mapped price_… | Amount, currency, interval, tax checked | Product/finance |
Keep the source ID for audit and support. Do not overwrite it before the destination object has been independently retrieved and compared.
Useful verification fields include:
- status and collection method;
- current period or next billing date;
- recurring items, quantities, currency, and amounts;
- trial end and cancellation state;
- default payment method presence;
- discounts and tax behaviour;
- business metadata used by the application.
Phase 3: Cut Over Credentials Safely
Stripe API keys authenticate requests for a specific account context. Move the application to destination credentials through the normal secret-management and deployment process:
- create the least-privilege production key needed by the application;
- store it in a secret manager, not source code;
- update the publishable key used by the browser or mobile client;
- test the destination account in a non-production environment;
- deploy the server and client changes together where required;
- verify the account ID returned by an authenticated request;
- rotate source credentials after the agreed observation window and personnel handover.
Do not reuse MoveMRR’s migration key as the application’s permanent billing key. The permissions and lifetime serve a different purpose.
Primary source: Stripe API-key best practices.
Phase 4: Recreate and Verify Webhooks
Webhook configuration is account-specific. A new endpoint has a new signing secret, even if the URL and enabled event types match.
For each destination endpoint:
- reproduce the intended URL, event types, and API version;
- copy the new
whsec_…signing secret into the application’s secret manager; - deploy signature verification before enabling production traffic;
- send a test event and verify a successful response;
- confirm deduplication by Event ID;
- handle events without relying on delivery order;
- retrieve current Stripe objects when an event arrives before a related object is present locally.
Stripe explicitly says event delivery order is not guaranteed. A resilient handler must also tolerate retries and duplicates.
Primary source: Receive and verify Stripe webhook events.
MoveMRR can optionally recreate supported webhook endpoint configuration in the destination account. The signing secret still needs an explicit application deployment because it is a credential, not ordinary endpoint metadata.
Phase 5: Protect Entitlements
The product should not grant or revoke access based only on a successful object-creation response.
Define the buyer’s source of truth:
- Stripe Entitlements, if the product uses them; or
- local entitlement records driven by verified subscription and invoice events.
At minimum, test:
invoice.paid;invoice.payment_failed;invoice.payment_action_required;- subscription created, updated, paused, resumed, and deleted;
- trial ending;
- past-due and unpaid policies;
- manual refunds or credits that affect access.
Stripe documents that subscription status and payment state are related but not interchangeable. For example, an active subscription does not prove that every historical invoice is paid.
Primary source: Using webhooks with subscriptions.
Phase 6: Reconcile Before Source Deactivation
Choose a gate that both buyer and seller can sign off:
- all in-scope rows have a destination object or an explicit exception;
- sample and aggregate recurring amounts reconcile;
- next billing dates and trial ends reconcile;
- the destination application resolves the new IDs;
- webhook signature verification and event processing pass;
- the customer portal and payment-update path use the destination account;
- the agreed source-deactivation action is complete or scheduled;
- manual follow-ups have owners and deadlines.
Do not infer success from equal subscription counts alone. Counts can match while prices, intervals, trial ends, tax behaviour, or local mappings differ.
Phase 7: Observe the First Renewal Cohorts
Monitor by renewal window, not only by elapsed time:
- destination invoice creation and payment;
- authentication-required and failed-payment events;
- duplicate source invoices;
- entitlement changes;
- webhook delivery failures;
- support tickets mentioning statement descriptors or payment updates;
- MRR and subscription counts against the signed reconciliation report.
Keep appropriate read access to the source account for historical invoices and logs. Stripe’s account-copy process does not move those records.
Limits
An ID map cannot automatically update every custom application, warehouse, CRM, tax tool, or data contract. Webhook recreation cannot transfer a signing secret. A successful migration also cannot guarantee future issuer authorization.
Assign a named engineering owner to the application cutover and a billing owner to the renewal observation period.