Fintech technology
Businesses Fintech August 21, 2026 • 12 min read

Cut Over to a New Payment Provider Without Losing Orders

For: Head of Engineering or CTO at a mid-size e-commerce or SaaS company processing 10K–200K transactions/month, who has already chosen a new payment provider and now cannot find an honest, sequenced plan for the actual cutover — not the integration docs, but the 72-hour window where both gateways are live, webhooks are firing from two sources, and one mis-sequenced step drops a live order silently

The riskiest moment in a payment gateway migration is not the switchover itself. It's the 30-day tail afterward, when the old provider keeps firing webhooks for refunds, disputes, and delayed captures on pre-migration charges that your new routing logic was never written to handle. Plan for the tail first, then work backwards to the cutover window. This playbook assumes you've already picked a provider, integrated it in staging, and now need an opinionated sequence for the live switch.

What follows is written for a Head of Engineering or CTO running 10K–200K transactions per month, with subscriptions, refunds, and disputes in the mix. If you're a checkout-only merchant with no recurring billing and no stored cards, you can skip about a third of this. Everyone else, read carefully.

The situation this applies to

You have:

If that's you, the seven steps below are the plan. Each has a checkpoint you can verify before moving to the next.

Step 1: Freeze the schema and add gateway-of-record to every payment object

Before you touch routing logic, your data model has to answer one question for every charge, refund, subscription, and dispute: which gateway owns this? If it can't, you will corrupt reconciliation state within the first hour of cutover.

Concretely:

Anti-pattern: A single “active_provider” config flag that flips globally. This forces every refund on an old-provider charge to go through your new provider, which will fail, and now your support team is manually processing refunds in two dashboards.

You'll know this step is done when: you can point at any payment record in production and, without looking at the created_at date, tell the system which API to call to refund it.

Step 2: Build a webhook router with strict source authentication

During the cutover window and for at least 30 days after, both providers will send you webhooks. Some events will be for the same underlying customer. Your webhook handler needs to be a router, not a switch.

Design:

Anti-pattern: Processing webhooks synchronously inside the HTTP request. During cutover you will see burst traffic, timeouts, provider retries, and duplicate processing. Async with idempotency is not optional at this volume.

You'll know this step is done when: you can replay the last 24 hours of production webhooks from either provider through the router and produce zero duplicate side effects.

Step 3: Reconcile OldPay to zero drift before you route a single new charge

You cannot debug a dual-gateway world if the single-gateway world is already broken. Most teams discover during cutover that their pre-migration reconciliation has been drifting for months — a few cents here, a stuck subscription there, a refund that fired in the dashboard but never updated the DB.

Run a full reconciliation against OldPay:

  1. Pull every charge, refund, and payout for the last 90 days via the OldPay API (not the dashboard export — the API is the source of truth).
  2. Diff against your database. Expect drift. Investigate every discrepancy, don't just null them out.
  3. Fix the root cause of any systemic drift — usually a webhook you dropped six months ago or a race condition on refund state.
  4. Get to zero drift, or a known and documented drift, before the cutover date. Not after.

You'll know this step is done when: your daily reconciliation job is green for seven consecutive days and any exceptions are individually explained.

Step 4: Route new charges to NewPay, but keep OldPay hot for everything else

This is the actual cutover, and it's the smallest, most boring step in the playbook. If steps 1–3 are done, this is a config change.

The rule for the cutover window (call it T-0 to T+72h):

Ship this behind a percentage rollout. Start at 1% of new charges to NewPay for the first two hours. Watch authorization rates, latency, and webhook throughput. Ramp to 10%, then 50%, then 100% over the first 24 hours. If NewPay's auth rate is materially lower than OldPay's on your traffic mix, you'll see it at 10% and can roll back cheaply.

Anti-pattern: Big-bang 100% cutover on a Friday night because “traffic is lower.” Traffic is lower and so is your on-call bench. Do the cutover on a Tuesday morning when the whole team is at their desks.

You'll know this step is done when: 100% of new charges are on NewPay, OldPay is still processing renewals and refunds correctly, and your dashboards show both gateways with expected volumes.

Step 5: Migrate stored payment methods deliberately, not opportunistically

If you have card-on-file or stored payment methods, this is where most migrations quietly fail. There are two approaches and you should pick one, not blend them.

Option A: Bulk token migration. Most major providers support importing tokenized card data from another PCI-compliant provider. This is a formal, PCI-DSS-governed process: you request it from NewPay, they coordinate with OldPay, and you receive tokens for your existing cards on NewPay. Every subscription can then be re-pointed. This is the cleanest option and the one I'd default to if your provider supports it.

Option B: Migrate on next successful charge. Leave existing subscriptions on OldPay. On next renewal, if the charge succeeds, use the returned card data to create a NewPay payment method for future charges. This works but takes a full billing cycle to complete, extending your dual-gateway tail from 30 days to 60–90.

Whichever you pick, track migration state per payment method: migration_status in {not_started, token_received, verified, failed}. Do not mark a method as migrated until you've successfully authorized against it on NewPay — a $0 auth or a low-value real charge. Bulk-imported tokens sometimes fail on first use for reasons neither provider explains.

Anti-pattern: Trusting that a bulk token import “worked” because the CSV was accepted. Verify with a live authorization.

You'll know this step is done when: every active subscription has a verified NewPay payment method and a successful renewal on NewPay, and OldPay's active subscription count is zero.

Step 6: Plan the 30-day tail as an explicit project, not a “we'll monitor it”

This is the step everyone skips and everyone regrets. After you're on NewPay for new charges, OldPay will keep firing webhooks for:

Your new routing logic almost certainly wasn't written to handle these gracefully because the developer writing it was thinking about NewPay. Common failure modes I've seen in this window:

Explicit tail-management actions:

  1. Keep OldPay's webhook endpoint fully live and monitored for at least 90 days. Alert on any drop in webhook volume — that's how you catch OldPay accidentally being disabled.
  2. Build a “legacy webhook” dashboard: count of events by type, per day, from OldPay. Volume should decay predictably. A spike means something's wrong.
  3. Explicitly write handlers for every OldPay event type that might arrive post-cutover, even if the handler is just “update the payment row and notify support.”
  4. Do not decommission OldPay API keys until you've had zero events for 30 consecutive days and your finance team confirms the final payout has landed.

You'll know this step is done when: OldPay's daily webhook volume is zero for 30 straight days, all disputes are closed, all payouts are received, and finance has signed off on final reconciliation.

Step 7: Reconcile daily against both providers until the tail closes

Your existing reconciliation job needs to become two jobs, or one job with a gateway dimension. Every day, for every gateway, compare provider-side truth to your database. Alert on any variance above a defined threshold (I'd start at zero and only raise it if you're drowning in noise).

What to reconcile:

If you're building this from scratch under time pressure, teams that have shipped fintech products before — the kind of work our GimBooks accounting SaaS and Cashpo lending platform case studies get into — usually already have reconciliation harnesses that can be adapted rather than written cold. Adapting is faster than greenfield.

You'll know this step is done when: reconciliation is green on both gateways for 30 consecutive days.

Failure modes I've seen

A short list of things that have actually gone wrong on real cutovers, in rough order of frequency:

None of this is exotic. All of it is preventable if you plan the tail before you plan the cutover.

Frequently Asked Questions

How long should I run both payment gateways in parallel?

Plan for a minimum of 90 days of dual-gateway operation after the cutover, driven by chargeback windows (typically 120 days from the original charge) and subscription cycles. Don't decommission OldPay API access until you've had 30 consecutive days of zero webhook events and finance has confirmed the final payout. Rushing this is the single most common cause of post-migration reconciliation nightmares.

Can I migrate stored cards without asking customers to re-enter them?

Usually yes, if both providers are PCI-DSS Level 1 compliant. Major providers like Stripe, Adyen, Braintree, and Checkout.com support formal card token migrations from each other — it's a paperwork-heavy process governed by PCI rules, not a self-serve feature. Contact your new provider's onboarding team early; the process can take weeks to arrange before you can even begin.

What's the safest day and time to run a payment cutover?

Tuesday or Wednesday morning in your primary business timezone, with the full engineering and finance team on-call and awake. Avoid Fridays (weekend on-call risk), Mondays (accumulated weekend traffic anomalies), and month-end / quarter-end (subscription renewal spikes and finance close). Ramp traffic to NewPay in percentage stages over 24 hours, not in a single flip.

How do I handle refunds on charges that were made on the old provider?

Always route refunds based on the gateway that processed the original charge, stored as a gateway field on the payment record. Never route refunds based on a global “active provider” flag. Your refund UI, whether in an admin panel or API, needs to branch on that field for as long as any refundable OldPay charge exists — typically 6–12 months after cutover.

What does a payment gateway migration cost and how long does it take?

It depends heavily on transaction volume, whether you have stored cards and subscriptions, how clean your current reconciliation is, and which providers are involved. For a realistic scope and sequenced plan for your specific stack, contact CodeNicely for a personalized assessment — a proper estimate needs to look at your actual payment surface area, not a generic template.

Found this useful? CodeNicely publishes engineering and product playbooks weekly. Browse the archive or tell us what you're building.