Web Applications
Payment provider migration for an online pharmacy
Built by Ronnel Ilagan
Moved a pharmacy's checkout from one payment provider to another without losing stored cards or a day of trading.
Builder email verified
Verification
- Type
- Professional
- Category
- Web Applications
- Published
- Jul 26, 2026
- Updated
- Jul 26, 2026
About this project
- The problem
The pharmacy's existing payment provider was raising fees and had twice had outages during evening peak, which for them is when most orders come in. Moving is easy to say and hard to do, because a few tens of thousands of customers had stored cards with the old provider, a chunk of the business was on repeat prescriptions that charge automatically, and the finance team's month-end depended on a settlement file whose format was about to change. The goal was a switch with no customer re-entering a card and no gap in the repeat-order charges, which is where the actual difficulty lives.
- My role
Contract backend developer, six months, working with two in-house developers and the company's finance lead. I was the only person who had done a provider migration before, so I wrote the plan and ran the cutover, and spent a surprising amount of the engagement in meetings with two providers' support teams rather than in an editor. I also did the on-call for the fortnight after cutover, which was the deal I made instead of a longer handover.
- What I owned
I owned the payment abstraction that let both providers run at once, the token migration, and the repeat-order charging path. The abstraction was not a grand interface — it was a thin seam over the four things we actually do — but getting the old integration behind it was most of the first two months. I ran the token migration with the two providers directly, which is a supported but slow process, and built the reconciliation that proved every stored card had landed. I also rewrote the settlement importer for finance and sat with them through two month-ends.
- Technical & product decisions
I insisted on running both providers in parallel behind a flag rather than cutting over in one night. That cost more in build and made the code uglier for two months, but it meant we could route one per cent of traffic, then repeat orders only, then everything, and route back within a minute. The in-house team's preference was a weekend big-bang, which is defensible and would have been faster if nothing went wrong. I also chose to keep the old provider connected for ninety days after the switch purely for refunds on historic orders, rather than write a migration for refund handling that would run once.
- Constraints
Refunds and repeat charges are regulated enough that the finance lead had to sign off on the reconciliation approach before anything moved, and the auditors asked for a record of every token that changed hands. The new provider's sandbox did not support the token import at all, so the first true test was in production against a small cohort. Prescription orders cannot simply fail — a declined repeat charge has a person waiting on medication at the end of it — so the retry and notification behaviour was specified by their pharmacy team, not by us.
- Result & impact
Cutover finished across nine days with no customer asked to re-enter a card and no repeat order missed; the reconciliation found three tokens that had not transferred, all of which were expired cards. Fees came down by a bit under a fifth, which was the point. Evening checkout failures dropped noticeably in the first month, though I would not claim all of that — the new provider is simply more reliable. The parallel-provider seam is still there and they used it again a year later to add a second local payment method without touching checkout.
- Who else worked on it
The finance lead effectively co-designed the reconciliation and caught a rounding difference between the two providers' settlement files that would have quietly diverged forever. One of the in-house developers took the customer-facing checkout work while I stayed on the plumbing, and he is the reason the failed-payment messaging is human rather than a code. The pharmacy team wrote the retry rules for repeat orders.