Shopify is good at a specific kind of invisibility: a merchant can run a global, multi-currency store with payment orchestration and inventory management and never once think about any of the three. That invisibility is the product. The moment you self-host, as we did migrating Increddy to a self-hosted Medusa v2 backend, all three become things your team builds, tests, and owns. Here's what that actually involved.
Multi-currency
Shopify handles currency conversion, rounding, and display formatting without a merchant writing a line of code. On a self-hosted backend, every part of that is a decision: which currencies to support, how to price a product that has no explicit price set in a given currency, what happens when a shopper switches currency mid-cart.
Increddy's checkout also separates display currency (a pure UI preference) from charge currency (what the card actually bills in), which Shopify's model doesn't naturally express. We cover that specific decision in display currency vs. charge currency.
Payment orchestration
Shopify Payments and its checkout handle authorization, capture, retries, and webhook delivery as a solved problem. Self-hosted, "a payment webhook retries" becomes a case your own code has to handle correctly, every time, including the version of the webhook that arrives twice or arrives after your system already moved on.
Increddy's order-fulfillment logic treats both the order-placement and payment-capture events as independent, retriable triggers, backed by a reconciliation job for whatever still falls through. That design, and why it's necessary, is the subject of how we made key delivery idempotent.
Inventory and reservation
Shopify's inventory system assumes a fairly generic model: a count goes down when an order is placed, and that's mostly it. A license-key business needs something more specific: a key reserved from a pool, assigned exactly once, with a defined behaviour for what happens when the pool runs out mid-checkout. None of that comes for free on any platform, including Shopify; it had to be built as custom logic either way, which was itself part of the original case for moving the backend.
| Kryeo | Reimplemented on self-hosted Medusa | |
|---|---|---|
| Multi-currency | Built: display/charge separation, cart-currency persistence | Shopify: built-in, limited control over the charge-currency split |
| Payment retries | Built: idempotent reservation across two independent triggers | Shopify: handled internally, not exposed for custom logic |
| Inventory/reservation | Built: license-key pool with reconciliation job | Shopify: generic count-based inventory, custom logic needed either way |
Scoping a self-hosted commerce build?
Tell us which of these three (currency, payments, inventory) matters most for your product. We'll tell you honestly how much work it actually is before you commit to owning it.
Talk to an engineer →The honest trade
None of this is an argument against self-hosting. It's an argument for knowing exactly what you're signing up for. Shopify's invisibility has a price (the revenue share, the extension ceiling); self-hosting's visibility has a different price (the engineering hours to build and maintain all three). For Increddy, where the reservation logic is the actual product, owning it was the right trade. For a simpler catalogue with no unusual commerce logic, it might not be. For the full migration story this sits inside, see how we replaced Shopify's backend without touching the frontend. We help teams make this trade-off explicitly under Medusa development engagements.