The brief was deceptively simple: “can you make our 140,000-product Stuller catalog into something we can actually sell from?” The catch was that the existing setup wasn’t a store at all — it was an iFrame on a brochure site. No checkout. No inventory truth. No analytics worth the name. Customers could browse, but they couldn’t buy. Conversion was happening, just not on the merchant’s terms.
This is the story of how we rebuilt that into a fully transactional Shopify Plus storefront — with live pricing, configurable merchant markup, and drop-ship fulfillment — without taking the legacy site down for a single hour.
The problem with iFrame catalogs
iFrame catalogs are appealing precisely because they’re cheap. The supplier hosts the inventory, you embed it, and your “store” is technically live by lunchtime. For the first year that feels like a win. By year three, you’ve absorbed every cost the cheap path defers: no SEO surface area (search engines can’t crawl iFrames meaningfully), no analytics (your tools see one URL, not 140,000), no checkout (the customer always leaves to complete the purchase elsewhere, often abandoning), and no merchandising control (the supplier decides what’s surfaced, in what order, with what copy).
The merchant we worked with was running into all of this at once. Their best-selling SKUs were buried under the supplier’s default sort. Their attempts to write category-page copy were fighting an iFrame that didn’t care. And their fulfillment team was rekeying every order by hand, because the iFrame and their warehouse system were two separate worlds.
Why Shopify Plus, specifically
We considered three platforms: Magento 2, BigCommerce, and Shopify Plus. Magento was the technical purist’s answer — best raw catalog modeling, deepest configurability — but the operational cost (hosting, security, dev time, talent availability) is brutal at this scale. BigCommerce had decent catalog primitives but the broader ecosystem was a step down. Shopify Plus won on three things: the editor experience for the merchandising team, the speed of getting to a working storefront, and the maturity of its API surface for the kind of supplier integrations we knew we’d need.
The risk we accepted: Shopify’s metafield + variant constraints would force us to be careful about how we modeled 140K SKUs. Spoiler: it worked, but the modeling phase took twice as long as the build itself.
Modeling 140,000 SKUs into Shopify’s grain
Shopify is opinionated about products. You get one product object, up to three options, and 100 variants per product. With a 140K-SKU jewelry catalog, the obvious naive mapping (one Shopify product per Stuller SKU) would pollute the admin and make collection pages unusable.
The actual model we landed on:
- Product = a stylistic family (e.g. “Solitaire Engagement Ring, Knife-Edge”).
- Variants = the saleable combinations within that family (metal, size, gemstone option).
- Metafields = the supplier-side facts that don’t drive variant choice (Stuller SKU, country of origin, certification, weight, supplier-side stock state).
This collapsed 140K raw SKUs into roughly 18,000 Shopify products with sensible variant explosion underneath. Search and collection pages stayed fast. The admin was navigable. And — crucially — the merchandising team could write copy at the family level instead of per-SKU.
The sync layer
Stuller’s feed updates constantly. Pricing moves with metal markets. Inventory state changes as items get reserved or fulfilled. We needed Shopify to mirror that without either platform becoming a single point of failure.
We built a sync worker that:
- Pulls Stuller’s delta feeds on a schedule and on webhook triggers.
- Writes to Shopify using the bulk operations API where possible, with idempotent operation IDs so retries are safe.
- Resolves conflicts deterministically — when Stuller says one thing and the merchant has overridden the field manually, the merchant override always wins, but we log the divergence so they can review it.
- Falls back to a queue when Shopify rate-limits us, instead of dropping writes.
The principle: any single sync operation must be safe to repeat. Idempotency is unsexy and saves you at 3am.
Dynamic pricing without the storefront feeling slow
Pricing was the hardest part. Gold and platinum prices move daily. Diamond prices move on supplier-specific schedules. Merchant markup rules are configurable per category, per supplier, per metal type, sometimes per individual SKU. Customers expect prices to feel current — but they also expect product pages to load fast.
We resolved this by separating pricing computation from pricing display. A background worker pre-computes the merchant-facing price for every SKU on every market-rate change, and pushes the result into a metafield. The storefront reads the cached metafield. The customer sees a fresh price; the storefront never has to call the pricing engine on the request path.
The trade-off is a small lag (up to fifteen minutes after a market-rate change), which is acceptable for a jewelry store but would not be acceptable for, say, a commodities exchange. Right tool for the job.
Drop-ship fulfillment routing
Once the order is placed, the storefront has to know which supplier to route the line item to. With a multi-supplier catalog, that routing logic lives in metafields. We wrote a fulfillment worker that:
- Splits the order into per-supplier chunks based on the metafield routing.
- Generates a per-supplier purchase order with the right billing/shipping context.
- Pushes the PO via the supplier’s API (or, in the worst case, drops a structured email).
- Listens for tracking updates and writes them back to Shopify so the customer sees one tracking timeline per supplier shipment.
From the customer’s perspective, they bought from one store. From the merchant’s perspective, the operations team has zero manual rekeying. From the supplier’s perspective, they got a clean PO that fits their ingestion system.
The cutover, in waves
We did not do a big-bang migration. We did the opposite — the legacy iFrame site stayed live for the entire build. Once the new Shopify storefront was working internally, we migrated traffic in waves:
- Week 1: a single, low-traffic category was redirected.
- Week 2–3: roughly 10% of catalog redirected. Monitored conversion, support tickets, fulfillment latency.
- Week 4–6: the rest, in increments. The legacy site kept serving anything we hadn’t migrated yet.
- End of week 6: the iFrame site was decommissioned.
This kept the blast radius of any bug small. If something broke in the new system, the legacy site still served the bulk of traffic. Zero downtime through the entire transition.
What we’d do differently
Two things, in retrospect.
First, we underestimated how much of the project was operational change management, not engineering. The merchandising team needed training. The fulfillment team needed new SOPs. We should have started those workstreams in parallel from day one, not at the end.
Second, we should have built the analytics layer earlier. We instrumented the new storefront properly, but we did it after the cutover started. The result was a two-week gap where we didn’t have clean conversion data to compare against the legacy baseline. Next time: telemetry on day one.
The takeaway
Migrating a 140K-SKU iFrame catalog to Shopify Plus is not, fundamentally, a Shopify problem. It’s a modeling problem and an operational problem in roughly equal parts. Get the model right and the platform stays out of your way. Get the operational change management right and the cutover is calm. The technology is the easy bit.
Working on a similar migration? Get in touch — happy to share what we learned in more detail.