All projects
Enterprise Commerce & Marketplace · Distributed Backend & APIs

Ecigone UK – Shopify to Medusa.js Migration

Headless commerce migration for a UK retailer

Role
Lead Full-Stack Commerce Engineer
Client
Ecigone UK

I planned and carried out the migration of ecigone.co.uk from Shopify to a headless Medusa.js stack. Tiered wholesale and retail pricing, loyalty points, UK age verification and the custom checkout all moved across, with no checkout downtime and no data loss.

  • Planned the full migration from Shopify to Medusa.js so that no store customisation or search ranking was lost.
  • Rebuilt Shopify app logic (wholesale pricing tiers, loyalty points, age verification) as native Medusa.js modules.
  • Wrote migration pipelines for 50,000+ customer records, orders and a product catalog with complex variants.
  • Added Redis caching and tuned PostgreSQL queries to keep responses under 100ms during UK flash promotions.
0sCheckout downtimeDatabase and DNS cutover with no interruption to orders
0Data loss50,000+ customer accounts, order histories and the catalog moved across intact
100%Customisations keptWholesale tiers, loyalty and age verification rebuilt in Medusa.js
<100msAPI response timeRedis-cached catalog and cart reads under peak UK traffic
  • Medusa.js
  • Node.js
  • Next.js
  • PostgreSQL
  • Redis
  • Shopify APIs
  • Stripe

Problem and objectives

The constraint was fixed from the start: no checkout downtime and no data loss during the move from Shopify to Medusa.js. The store takes 100 to 200+ orders every day, so any interruption would have cost real sales.

Ecigone had outgrown Shopify. Its B2B and B2C pricing tiers, the age verification rules that apply to vape products in the UK and its checkout customisations all depended on apps and workarounds. The goal was to move the whole store to Medusa.js while keeping every piece of business logic, the order history and the existing search rankings, without taking checkout offline.

Architecture

Architecture diagram of the Ecigone UK Shopify to Medusa.js migration: migration scripts into PostgreSQL, Medusa.js backend, Redis cache, Next.js storefront and Stripe.

Diagram: the Ecigone UK Shopify to Medusa.js migration.

The new stack is a modular Medusa.js backend behind a Next.js App Router storefront. Logic that lived in Shopify apps and Liquid was rebuilt as Medusa services, subscribers and API routes: tiered pricing, loyalty points, bundle builders, tax and shipping rules.

Migration scripts moved 50,000+ customer accounts, order histories and the product catalog into PostgreSQL, along with redirects for every indexed URL. Redis caches catalog and cart reads, which keeps API responses under 100ms during flash sales. Compliance modules handle 18+ age verification and restricted-goods shipping rules.

Migration sequence

The store kept trading throughout the move, at 100 to 200+ orders a day. In order:

  1. Rebuilt the business logic as Medusa.js modules (tiered pricing, loyalty points, age verification, bundle builders, tax and shipping rules) while Shopify stayed live.
  2. Wrote repeatable migration scripts and ran them against a staging PostgreSQL database: 50,000+ customer accounts, order histories and the full catalog.
  3. Rehearsed the cutover end to end on staging, including the redirect map covering every indexed URL.
  4. Cut over the database and DNS in a single window, with Shopify still reachable as the fallback until the new stack was verified.

Cutover validation

Before switching traffic, I verified on the migrated data:

  • Record counts matched between Shopify and PostgreSQL: 50,000+ customer accounts, plus orders, products and variants.
  • Spot-checked wholesale pricing tiers, retail prices, loyalty point balances and age-verification rules against the live store.
  • Placed test orders end to end through the new checkout, including payment capture and a refund.
  • Checked the redirect map returned 301s for the top indexed URLs and that page metadata carried over.

Rollback plan

DNS was the only hard switch. The Shopify store stayed intact during cutover, so rolling back meant pointing DNS back.

Cutting search latency from 40s to under 6s across 200,000+ SKUs: the sub-100ms reads on this project use the same cache-first approach.