Last updated: 2026-08-09 · By Abdul Razzaq · ~15-min read

TL;DR — A safe Shopify migration in 2026 is a three-phase job: freeze writes, transform the catalog, cut over DNS. Do a 12-item pre-audit, build a 1:1 redirect map before you touch DNS, use Matrixify or the Shopify Migrate app for bulk import, Rewind for backups, and keep Klaviyo, Judge.me, and Meta pixels re-attached inside a 60-minute cutover window with DNS TTL pre-lowered to 300 seconds.

I’ve run three migrations across three source platforms in the last 24 months. One was a 50,000-SKU Magento Commerce apparel merchant moving to Shopify Plus — enterprise complexity, EAV schema quirks, and a redirect map with more than a million rows once you counted paginated collections. Another was 783 Label, a Square retailer moving to Shopify with 3,000+ SKUs and a physical store that couldn’t afford to have inventory drift by a single unit during cutover. The third was Lantern Independent (Lindie), a custom audiobook platform with 700+ digital titles, an AWS Lambda audio pipeline, and customers listening in every time zone on Earth.

Different catalogs. Different data models. The same three-phase framework — freeze, transform, cut over — worked in all three. This is that framework as a checklist, written the way I actually run it in 2026, with the specific gotchas I keep seeing on rescue projects I get called into after somebody else’s migration went sideways. If you want the compressed version, the platform migration service page has the deliverable list. If you want the full playbook, keep reading.

Shopify’s own migration developer docs are a good API reference — they are not a plan. This is the plan.

The pre-migration audit that saves the project

Every Shopify migration checklist starts with an audit — not a discovery call, an actual data audit against the source platform. In 2026 the audit is what separates a 6-week migration from a 14-week rescue. It surfaces the hidden objects — attributes, tax overrides, currency rules, saved carts, subscription tokens — that break silently on cut-over day if you skip them.

Run this 12-item audit before you write a single line of transformation code:

  1. Full product export from source — including archived and out-of-stock SKUs. Merchants forget the archived ones.
  2. Attribute / variant matrix — for Magento, dump every configurable/simple/bundle relationship. On one 50K-SKU Magento migration, this audit surfaced 4,200 attribute variants nobody knew existed because they were bound to a legacy price rule.
  3. Inventory locations — Square uses per-location stock; Shopify needs the same locations pre-created before any inventory import touches the store.
  4. Customer table — passwords cannot migrate cleanly. Plan the forced password-reset email on cutover.
  5. Order history — decide whether you’re importing all orders, last 24 months, or none. Import cost and reporting continuity trade off directly.
  6. Coupon and discount rules — Shopify’s automatic discount model does not map 1:1 to Magento cart rules. Document the deltas now, not at UAT.
  7. Metafields plan — every source attribute that isn’t a Shopify-native field becomes a metafield definition. Draft the schema before import.
  8. Redirect map source — export every indexable URL from Google Search Console, Screaming Frog, and the source CMS. Three sources, deduped.
  9. Integration inventory — Klaviyo, Judge.me, Gorgias, Meta pixel, TikTok pixel, Google Merchant Center feed, ERP, WMS. Each one needs a re-attach step post-cutover.
  10. App parity — for every source-platform module (Magento extensions, Square add-ons), identify the Shopify app equivalent or the custom build that replaces it.
  11. Content pages, blog, and media — these get skipped and then blamed on the developer.
  12. Legal + tax config — tax rates, tax overrides, digital vs. physical classifications, and regional VAT/GST rules.

The audit output is a single spreadsheet — one row per object, source count, target count, mapping decision, owner. If a row is blank, the migration isn’t ready to start.

Data model — what breaks in Shopify’s schema, and how to fix it

The second phase of any Shopify migration checklist is the schema fight. Shopify has an opinionated data model — flat product, variant array, metafields for the rest. Magento, Square, and custom stacks all model their catalogs differently, so every migration has a translation layer. If you skip the mapping doc, that translation layer gets improvised at 2am on cut-over night.

Here is the mapping table I use as a starting point. Every project extends it, but the columns don’t change.

Source concept Magento (Enterprise) Square (POS) Custom stack (Lindie) Shopify target
Product catalog_product_entity (EAV) Catalog.CatalogItem Postgres titles products.json
Variant Configurable + child simple ItemVariation Format rows (MP3/M4B/streaming) variants array
SKU sku attribute sku on variation isbn or sku variants[].sku
Inventory cataloginventory_stock_item per warehouse InventoryCount per location_id Not stocked (digital) inventoryLevels per location_id
Media media_gallery + pub/media image_ids on CatalogItem S3 URLs productImages (rehosted)
Attributes EAV attributes (unbounded) Modifier lists JSON metadata column Metafields (namespace/key)
Category Categories tree Categories series + genre tables Collections (manual/smart)
Customer customer_entity Customer.customer users table customers + metafields
Digital delivery Downloadable products module n/a S3 signed URLs from Lambda Digital Downloads app or custom app

The 783 Label migration is where inventory precision matters most. Square models inventory as a stock count per location_id per ItemVariation. Shopify models it as an InventoryLevel per location_id per variant, but the store must have those locations created before you import a single unit. On the 783 Label cut-over I created the Shopify locations first, seeded them with zero stock, then set inventory to the exact final Square counts inside the freeze window. The reconciliation report was one row per SKU per location: Square count, Shopify count, delta. Deltas that weren’t zero got investigated before we opened the store. Zero drift, unit for unit.

The Magento side has different gotchas. Configurable products with more than two attribute axes (say, size × color × material) don’t map cleanly — Shopify caps you at three option axes and 100 variants per product without Shopify Plus expansion. On the 50K-SKU enterprise migration, roughly 8% of the catalog needed variant restructuring or split-into-multiple-products before it would import. That work is scriptable, but only if you find it in the audit, not at import time.

Lindie’s data model was custom, which is easier to migrate than either commercial platform — you own the source of truth, so you can shape the extract to fit Shopify. The audio files themselves stayed on AWS S3 with Lambda-signed URLs; Shopify only held product metadata, the storefront, and the checkout. Not every migration needs to move every byte.

SEO preservation — the redirect map that keeps rankings

An SEO-safe Shopify migration is a 301 redirect map plus a canonical strategy. Skip either and you lose rankings the week after cutover. Shopify’s URL structure is fixed — /products/handle, /collections/handle, /pages/handle, /blogs/handle/article-handle — so almost every source URL will change shape even if the handle stays identical. That means a per-URL redirect for every indexable page, not a pattern rewrite.

Build the redirect map from three sources deduped: Google Search Console’s exported “Pages” list (last 16 months), a full Screaming Frog crawl of the source domain, and the source CMS’s own URL export. Merge on source URL, keep the row with the most recent GSC impression, and you have a canonical list of what actually needs to redirect. Anything without a GSC impression in 16 months and no internal links can 410 — pruning dead URLs is faster than redirecting them.

The map itself is a CSV with four columns: source_url, target_url, status_code, notes. Every row is a 301 unless it’s a genuine 410. Import into Shopify via Matrixify’s URL Redirects sheet — the admin UI cap is around 100,000 redirects per store, which is one of the reasons very large catalogs need pattern-based edge redirects at Cloudflare or Fastly instead of doing everything inside Shopify.

Test the map at scale before cutover. I use a Node script that hits every source URL against the staging Shopify domain (with a host header rewrite) and asserts a 301 to the expected target with no redirect chains. On the 50K-SKU Magento migration, the first pass of the redirect script failed on roughly 3% of URLs — mostly paginated collection pages and legacy filter permutations. Fixing those before DNS cut is the difference between keeping organic traffic in the 90-day window after cutover and watching it fall off a cliff.

Google’s site move with URL changes documentation is the authoritative reference for the change-of-address signal and the crawl-recovery pattern. Two things it emphasizes that migration guides routinely miss: keep the old URLs redirecting for at least 180 days (a year is safer), and submit both old and new sitemaps in Search Console so Google can re-crawl at pace.

The other quiet killer is canonical tags. Shopify auto-generates canonicals to /products/handle even when a product is reachable through /collections/handle/products/handle. Verify the canonicals point to the primary URL after import — a broken canonical can cost you 20-30% of a product page’s authority without triggering any obvious error.

If you want the SEO preservation work bundled into the migration itself rather than run separately, the platform migration service covers the redirect map, the canonical audit, and the 90-day post-cutover ranking watch.

Zero-downtime cutover — the DNS + freeze protocol

Zero-downtime cutover is not the same as zero-freeze. Every migration has a freeze window — a period when the source platform stops taking writes so the final delta sync can complete cleanly. What “zero downtime” means in practice is that the storefront stays purchasable throughout, either from the source domain (during freeze) or the new Shopify domain (after DNS cut), with no visible outage to a shopper. On the three migrations I’ve shipped, that window has ranged from 20 minutes to under a 60-minute cutover window. Longer than that and you’re doing something wrong.

The protocol is a sequence, and every step has a rollback. Here is the flow I run:

flowchart TD
    Start(["T-24h: Pre-cutover
DNS TTL lowered to 300s"]) --> A["T-2h
Final full backup
Source + Shopify"] A --> B["T-0
Freeze writes on source
Checkout stays live, admin locked"] B --> C["T+5m
Delta sync
Orders + inventory + customers"] C --> D["T+20m
Reconciliation
Row counts + SKU deltas"] D --> E["T+30m
DNS cut
Domain points at Shopify"] E --> F["T+35m
Verify checkout
Test order + payment capture"] F --> G["T+45m
Re-attach integrations
Klaviyo, Judge.me, Meta, GMC"] G --> H["T+60m
Unfreeze
Shopify admin opens"] H --> Q{"Test order
captured cleanly?"} Q -->|Yes| Live(["Live, begin 30-day watch"]) Q -->|No| Roll(["Rollback DNS
Investigate delta"]) classDef step fill:#0e1218,stroke:#00d9a3,stroke-width:1px,color:#e8ecef classDef decision fill:#1a1f2b,stroke:#f5a742,stroke-width:1px,color:#e8ecef classDef good fill:#0f2818,stroke:#7dd88a,stroke-width:1.5px,color:#e8ecef classDef bad fill:#281818,stroke:#f28080,stroke-width:1.5px,color:#e8ecef class A,B,C,D,E,F,G,H step class Q decision class Live good class Roll bad

Two rules of thumb make this protocol survive real conditions. First, lower DNS TTL to 300 seconds at least 24 hours before cutover — that gives resolvers enough time to see the short TTL before you cut, so propagation after the cut is measured in single-digit minutes rather than hours. Second, freeze the source admin, not the source storefront — shoppers can keep browsing and checking out on the source until the moment DNS flips, at which point in-flight sessions gracefully route to the new store. That’s what keeps the window “zero downtime” from a shopper’s point of view.

The Lindie cutover is the sharpest example of why timing matters. Audiobook customers listen at 3am local time, and they listen for hours. A cutover window at 2am Pacific meant 10am in London and 5am in Sydney — no clean shopper-lull moment across all time zones. The freeze period had to be short enough that even a listener who started a book five minutes before freeze could keep listening — the S3 signed URLs stayed valid through the DNS cut because they weren’t domain-bound. Not every migration has that kind of latitude. The 783 Label cutover ran during their closed retail hours specifically because we wanted zero POS activity during the freeze.

Finally, keep a written rollback trigger posted in the room during cutover: if the test order fails to capture, if inventory reconciliation shows deltas over N units, if the checkout returns any 5xx, DNS gets flipped back to source and the go/no-go conversation happens off the clock. Having the trigger written down beats having it argued in the moment.

Where most migration guides get the tool stack wrong

There is no single tool that handles every Shopify migration cleanly. The stack I reach for depends on catalog size, source platform, and how much custom logic sits between the source data and the Shopify shape.

Tool When it earns its spot Where it fails
Matrixify Anything over 5,000 SKUs, complex metafields, bulk redirects. Handles Magento, WooCommerce, Wix, custom CSV exports. Not free at scale — pricing scales with items. Learning curve on the Excel schema is steep on day one.
Rewind Backup before every write during freeze + delta phases. Non-negotiable for production stores. Not a migration tool — a safety net. Doesn’t move data cleanly across platforms.
Shopify Migrate app Native imports from BigCommerce, WooCommerce, Squarespace, Wix. Free, official, handles the common cases well. Limited flexibility on custom mappings; enterprise Magento is out of scope.
LitExtension Turnkey migrations for small merchants on WooCommerce, Magento 1.x, PrestaShop who want a done-for-you flow. Opaque process — you don’t own the transformation logic, so debugging post-migration issues is harder.
Custom Node/TypeScript scripts Enterprise migrations (50K+ SKUs), custom stacks like Lindie, anything with non-standard transformation logic. Uses Shopify’s Bulk Operations API + GraphQL Admin API. Build cost. Only worth it above a complexity threshold.
Screaming Frog + GSC export Redirect map source-of-truth. Every migration uses these. Not a migration tool — a discovery tool.

The honest contrarian take: Matrixify is the default, not the only answer. For the 50K-SKU Magento migration I ran a hybrid — Matrixify for the bulk product and customer import, custom Node scripts for the variant restructuring on the 8% of the catalog that needed splitting, and the Bulk Operations API for the inventory-level updates because Matrixify’s inventory sheet was slower than direct GraphQL at that scale. For Lindie I skipped Matrixify entirely because the source was our own Postgres — a custom script running the Admin API was faster to write than mapping the export to Matrixify’s schema.

The Shopify Migrate app is genuinely good for the merchants it targets — small-to-mid Woo, Squarespace, BigCommerce. If your catalog is under 5,000 SKUs and your source is one of those, try Migrate first before you pay for anything. The reason I don’t use it on the projects I ship is that they’re all outside its supported source list.

The 30-day post-migration checklist most guides skip

Cutover is the middle of the migration, not the end. The 30 days after DNS cut are where you catch the silent failures — a Klaviyo flow that stopped firing, a redirect that landed on the wrong collection, a Meta pixel that lost its purchase event. Every Shopify migration checklist worth its name has a post-cutover phase.

Day-of-cutover verification, in this order:

  1. Test order end-to-end. Real payment, real capture, real fulfillment webhook fires. Refund the test order after.
  2. Run the redirect script in production. Same script from staging, hit against the live domain. Zero failures expected.
  3. Google Search Console URL Inspection on the top 20 traffic pages. Confirm indexable, canonical correct, structured data valid.
  4. Structured data audit. Product schema, breadcrumb schema, organization schema — run Google’s Rich Results Test on samples.
  5. Klaviyo, Judge.me, Gorgias re-attach verification. Fire a test event through each and confirm it lands.
  6. Meta Pixel + TikTok Pixel + GA4 — trigger a PageView, an AddToCart, a Purchase, and verify events land in each platform’s debug view.
  7. Google Merchant Center feed — resubmit the feed, watch for disapprovals over the first 72 hours.

Then the 30-day watch:

  • Weekly GSC coverage report — indexed pages should trend up, not down. A drop of more than 15% by week 2 means the redirect map has holes.
  • Weekly organic sessions vs. 90-day pre-cutover baseline — expect a 5-15% dip in weeks 1-2, recovering by week 4. Deeper or longer drops are a signal.
  • Daily error rate monitoring for the first week — Shopify’s admin surfaces script errors, checkout errors, and API errors. Watch the trend, not just the count.
  • Order reconciliation with prior platform for the first two weeks — confirm no order data drift.

On the 50K-SKU Magento migration, the 30-day watch caught two things we would have missed otherwise: a legacy blog URL pattern that hadn’t been redirected (surfaced by a GSC coverage drop in week 2), and a Klaviyo flow trigger that stopped firing because the event property name had changed shape in Shopify’s default schema. Both fixable in an afternoon once you know they exist.

Common failure modes (from projects I got called in to rescue)

I get called into rescue projects a few times a year, most of them after somebody else’s Shopify migration. The failure patterns rhyme. Here are the ones I keep seeing in 2026:

Redirect map built from the sitemap only. The sitemap misses paginated collection pages, filter permutations, and any URL that had traffic but wasn’t linked from the source’s navigation. The fix is the three-source dedupe from the SEO section above — GSC + Screaming Frog + CMS export. Sitemap-only maps typically miss 15-30% of real-traffic URLs.

No canonical audit post-import. Shopify auto-generates canonicals, but if products are reachable through collection subpaths, some themes serve the collection-subpath URL as the canonical. Google then treats the primary product URL as duplicate. I’ve seen this cost a merchant a third of their product-page authority in a month.

Password migration attempted instead of forced reset. You cannot migrate hashed passwords from Magento or Square into Shopify — the hashing algorithms don’t line up and Shopify won’t accept raw hash imports. Every customer needs a password reset email at cutover. Skipping this leaves customers unable to log in and blaming the migration.

Inventory imported before locations exist. Shopify silently defaults inventory to the primary location if you import without creating your locations first. On a multi-warehouse migration this looks fine in the admin until the first fulfillment call routes to the wrong warehouse.

No test order in staging before cutover. Every migration needs a real end-to-end test order — payment capture, fulfillment webhook, notification email, refund — run against the staging store before DNS cut. Half the rescue calls I get would have been caught by this one step.

Third-party pixel re-attach forgotten. Meta, TikTok, Google Ads pixels all need their event mapping re-verified after cutover. Shopify’s native event names don’t always match what the source platform was firing. Purchase attribution can disappear silently for weeks.

Klaviyo flows left pointing at old product URLs. Flows that reference product handles or URLs need updating even if the handle stayed the same, because the domain in the URL changed. Abandoned-cart emails that link to oldstore.com/products/xyz after cutover convert at zero.

When to hire a specialist vs. run it in-house

Not every migration needs a specialist. Some do. The honest decision matrix:

Migration profile Run in-house Hire a specialist
Under 500 SKUs, WooCommerce or Squarespace source, no custom logic Yes — Shopify Migrate app + weekend Overkill
500–5,000 SKUs, standard integrations, small team Yes if you have a mid-level dev Consider if timeline is tight
5,000–50,000 SKUs, Magento/BigCommerce, multiple integrations Marginal — high rescue risk Yes
50,000+ SKUs, enterprise complexity, Shopify Plus target No Yes — this is where things go wrong at scale
Any migration where downtime costs revenue by the hour No Yes
Any migration where the source data is custom-schema Only if you own the source Yes

If you’re deciding whether the person you’re hiring is right for the migration, the Shopify developer vetting playbook has the 20-minute filter I use — it works for migration specialists the same way it works for theme developers.

Frequently asked questions about Shopify migrations

How long does a Shopify migration take?

Realistic ranges in 2026: 4–6 weeks for a mid-market DTC brand under 5,000 SKUs with standard integrations, 8–14 weeks for larger catalogs (5K–50K SKUs), and 12–20 weeks for enterprise migrations with complex B2B rules or heavy integration counts. The 50,000-SKU Magento migration I ran was in the enterprise band. The 783 Label Square migration ran shorter because retail catalogs typically have simpler variant models.

Will my SEO rankings survive a Shopify migration?

Yes, if you build the redirect map from three sources deduped, keep canonicals pointing at primary URLs, and submit both sitemaps to Search Console at cutover. Expect a 5–15% organic dip in weeks 1–2 with recovery by week 4. Persistent drops beyond that mean holes in the redirect map — usually paginated or filter URLs.

Can I really migrate with zero downtime?

Yes, from a shopper’s point of view. What you cannot avoid is a freeze window on the source admin — usually 20–60 minutes — during which staff can’t edit orders or inventory. Shoppers stay purchasable throughout, either on the source domain (during freeze) or the new Shopify domain (after DNS cut). “Zero downtime” and “zero freeze” are different promises.

What breaks most often during a Magento → Shopify migration?

Three things: configurable products with more than three attribute axes (Shopify caps at three), EAV attributes that never made it into anyone’s documentation (the audit surfaces them), and Magento cart rules that don’t map to Shopify’s automatic discounts. Each is scriptable to work around, but only if you find them in the pre-migration audit rather than at import time.

How do I migrate inventory precisely from Square?

Create your Shopify locations first with matching names to the Square locations. Seed each location with zero stock. Inside the freeze window, extract the current Square inventory count per SKU per location, set the exact final numbers in Shopify via the InventoryLevel API, and run a reconciliation report row-per-SKU-per-location before opening the store. On the 783 Label migration this process gave zero drift, unit for unit.

Do I need Shopify Plus for a large migration?

For catalogs under about 25,000 SKUs, standard Shopify works. Above that, or if you need checkout extensibility, B2B pricing rules, expanded API rate limits, or the higher variant caps, Shopify Plus becomes the right target. The enterprise 50K-SKU migration I ran needed Plus specifically for the API rate limits during the bulk import — standard Shopify would have taken days longer just from throttling.

What’s the biggest hidden cost of a Shopify migration?

App parity. Every source-platform module or extension has a Shopify equivalent, but “equivalent” often means “close enough with configuration” and sometimes means “requires a custom build.” Budget 20–30% of the migration total for app selection, configuration, and any custom middleware to replace source functionality that doesn’t exist as a Shopify app.

How should I test the migration before going live?

Full end-to-end on a staging Shopify store with a host header rewrite pointed at the redirect map. Run a real test order with payment capture, fire test events through every integration (Klaviyo, Meta, GMC), run the redirect script against staging with zero-failure assertion, and get sign-off from a checklist of at least 30 acceptance items before you touch DNS. If you can’t sign off staging cleanly, cutover isn’t ready.


About the author

Abdul Razzaq is a Shopify developer based in Lahore, Pakistan. He’s shipped 50+ stores including a 50,000-SKU Magento Commerce migration to Shopify Plus, the 783 Label Square-to-Shopify migration with 3,000+ SKUs and zero inventory drift, and the Lantern Independent (Lindie) audiobook Shopify Plus platform — 700+ titles running against an AWS Lambda audio pipeline. 7+ years in the Shopify trenches, 5★ across 30+ reviews on Fiverr and Upwork. He leads Shopify development at QWERTY Experts and takes select freelance projects. More writing on the devabdulrazzaq blog.

Read the full bio → · LinkedIn · GitHub