Most "we migrated off Shopify" posts are about moving a catalogue from one platform to another. This one is about something narrower and, we think, more interesting: replacing an entire commerce backend, cart, checkout, payments, inventory, under a storefront that stayed live and unchanged the whole time, for Increddy, a digital-goods storefront selling game and software license keys.

The constraint that shaped everything

Increddy's frontend, a Next.js app with Zustand for client state and React Query for data fetching, already worked. It talked to Shopify's Storefront API for cart and checkout. The brief was not "rebuild the site." It was "replace what's behind it," which meant the new backend had to produce exactly the API shape the existing frontend already expected, or close enough that the frontend changes were additive, not a rewrite.

That constraint ruled out the usual approach of designing a backend from a specification document. A spec written in isolation would drift from what the frontend actually called, how it actually shaped a cart response, which fields it actually read off a product. So we did the opposite.

Frontend as source of truth

Before writing a line of backend code, we read the live frontend codebase end to end, feature by feature, to determine the exact API contract it needed. Not what a commerce platform typically provides, what this specific frontend, built for this specific product, actually called and expected back. That became the backend's spec.

Two teams, two repos, one contract

Backend and frontend lived in separate git repositories, owned by separate people, developed in parallel rather than sequentially. Keeping that parallel work from diverging took two structured documents: a gap tracker mapping every frontend data need to a backend capability, and matched backend-task and frontend-task lists with explicit dependency IDs so each side knew exactly what it was waiting on.

The discipline that made this actually work was smaller than the documents: both teams were instructed to verify every claim against running code and a live backend, not against the other side's status notes. Several claims in the backend's own progress notes turned out to be wrong or incomplete once checked against the live system. Catching that early, against reality, is cheaper than catching it in a staging walkthrough three weeks later.

Replacing a commerce backend under a live storefront?

Tell us what's live today and what's not working. We'll tell you honestly whether a clean cutover like this fits your situation.

Talk to an engineer →

No data migration, by design

Because this was framed as a clean cutover rather than a data migration, no Shopify orders, customers, or catalog data were carried over. The new Medusa backend was built and populated from scratch. This sounds like it throws away history, and in a sense it does, but it also removes the single riskiest part of most replatforms: a migration script quietly mis-mapping edge-case records that only surface as support tickets weeks after launch. For a business where the backend was being rebuilt rather than translated, starting clean was the lower-risk choice, not a shortcut.

What this took that a platform usually hides

Shopify abstracts away multi-currency handling, payment orchestration, and inventory logic well enough that most merchants never think about them. A self-hosted Medusa backend has to reimplement all of it deliberately: as custom modules, custom routes, and custom subscribers reacting to commerce events. That's the real cost of ownership, and it's worth naming plainly rather than glossing over, because it's exactly the work an agency that hasn't done this before will underestimate.

For the specific race-condition problem this surfaced in order fulfillment, see how we made Increddy's key delivery idempotent. For the currency-model decision behind the checkout, see display currency vs. charge currency. We run this kind of backend replacement under Medusa development engagements.