Neckles IO Back to Work

E-Commerce Operations

Moving a Product Catalogue from QuickBooks to Shopify Without Wrecking the Store

By Alejandro Neckles · June 2026

A surprising number of retail businesses keep their entire product catalogue in QuickBooks. Not because anyone chose it as a product database, but because it was the first system that needed product records. Every invoice line item requires an item, every item needs a price and a SKU, and over the years the accounting file quietly becomes the only complete record of what the business sells.

QuickBooks is good at that job right up until the business wants a real online store. Then the catalogue is in the wrong place. Shopify needs products, variants, options, images, and collections. QuickBooks has items, sub-items, and a price field. The shapes do not match, and the data has to move.

How it moves determines whether the store launches clean or launches broken.

The two obvious paths, and why both fail

The first path is manual retyping. Someone (usually the owner, or whoever is least able to refuse) opens QuickBooks in one window and Shopify admin in the other and starts entering products. For a catalogue of any real size this is weeks of labour, and it is the kind of labour that produces transcription errors: a price keyed with a digit transposed, a SKU copied from the row above, a variant skipped because the phone rang. The errors are invisible until a customer orders the wrong thing at the wrong price.

The second path is the one-shot CSV import. Export everything, wrestle it into Shopify's template, upload, and hope. The failure mode here is sharper. Large imports fail partway (a malformed row, a rate limit, a timeout), and when they do, you have a half-populated store and no record of which half. The import tool does not tell you where it stopped. Running it again creates duplicates of everything that did go through. At that point the cleanup is often more work than the migration was supposed to be, and it is happening in the live store.

There is also a quieter problem both paths inherit: the source data is rarely as clean as the owner believes. Accounting items accumulate cruft over a decade: discontinued products never deactivated, near-duplicate items created during a busy season, descriptions written for an invoice line rather than a customer's screen. A migration that copies the catalogue faithfully copies the cruft faithfully too. The export deserves a review pass before anything moves: what is actually for sale, what is dead, and what needs a real product description instead of an internal shorthand. That review is far cheaper before migration than after launch.

Both paths share the same flaw: they treat the migration as a single event that either works or does not. Real migrations get interrupted. Connections drop, APIs throttle, source data turns out to be dirtier than anyone admitted. A migration designed on the assumption that nothing will go wrong is designed to go wrong expensively.

What a migration built like infrastructure looks like

The alternative is to build the migration as a pipeline with the properties you would demand of any production system.

Small batches. Products move in batches of a manageable size, not in one monolithic push. A failure affects one batch, not the whole catalogue, and the blast radius of any bad record is bounded.

Checkpointed progress. After every batch, the pipeline records what it has done. If anything interrupts the run (a network failure, a rate limit, a deliberate stop), it resumes exactly where it left off. Interruptions cost minutes, not a restart from zero, and never produce a store where nobody knows what made it across.

Variants carried whole. A product is not just a title. Variants carry their options, SKUs, prices, and compare-at pricing as a unit. The migration that moves product titles and leaves the variant structure for "later" has not migrated the catalogue; it has migrated a list of names.

Collections created once and remembered. Categories in the source data become Shopify collections, created on first encounter and reused on every subsequent reference. Without that memory, every run that touches a category mints a fresh duplicate collection, and the store's navigation decays with each pass.

Idempotent re-runs. This is the property that separates a tool from a script. Run the pipeline a second time, against the same export or an updated one, and it converges on the correct state instead of duplicating it. Idempotence is what makes the migration safe to operate rather than merely possible to execute. It also means the same pipeline can absorb a corrected export next week without anyone holding their breath.

We built the migration this way for NRG Alternatives, a lighting retailer whose full catalogue (products, variants, options, collections) lived in QuickBooks and now lives on Shopify, moved in checkpointed batches by a pipeline that was safe to run again at every step.

Verify before you announce

A migration is not done when the pipeline finishes. It is done when the result has been checked against the source, and that check should happen before the store is announced to a single customer.

The verification is mechanical, which is exactly why it should not be skipped. Count products in the source and count them in Shopify; the numbers must reconcile, and any gap must be explainable record by record. Spot-check variants against the source: not a casual scroll, but a deliberate sample across product types, confirming SKUs, prices, and compare-at values survived intact. Walk the collections and confirm each one exists exactly once and contains what it should. Then place a test order. Pricing errors that survive every spreadsheet review tend to surface at checkout.

The cost of this verification is an afternoon. The cost of skipping it is discovering the missing third of the catalogue from a customer email two weeks after launch.

After the migration: the alignment problem

A clean migration solves the catalogue problem once. It does not solve it permanently, because the business now has two systems that both believe they know the product list. QuickBooks keeps receiving purchases and adjustments because the accounting still lives there. Shopify keeps selling. From the day the store launches, the two records start to drift.

Keeping inventory and pricing aligned between the accounting system and the storefront is the next problem, and it deserves to be treated as its own project, not bolted on in the closing days of a migration. It has different failure modes (sync conflicts, partial updates, the question of which system wins when they disagree), and it needs the same engineering posture: scoped credentials, bounded writes, and behaviour that is safe under retry. The migration pipeline, if it was built properly, becomes the foundation that ongoing sync stands on. That is the right order of operations: move the catalogue correctly first, then decide how the two systems stay in agreement.

What you should not do is let the absence of a sync push you back into manual double-entry. A weekly reconciliation routine with a clear owner is unglamorous and entirely adequate while the proper integration is scoped. In our engagements, the businesses that get into trouble are not the ones running an interim manual process. They are the ones pretending the drift is not happening.

The test to apply

If someone proposes a catalogue migration, ask one question: what happens if it stops halfway? If the answer involves starting over, deleting duplicates, or figuring out manually what made it across, the migration has not been designed yet. The honest answer is boring (it resumes from the last checkpoint and converges), and boring is what you want standing between your accounting file and your storefront.

If your product catalogue lives in your accounting software, getting it out is an engineering problem, not a data-entry project.

Neckles IO builds resumable, duplicate-safe catalogue migrations for retailers moving onto Shopify.

Inquire about your catalogue

Related reading