The Reluctant Guide to Shopify Migrations

Act IV: The Joinery

Apps Are A Governance Problem In Disguise

The brand did three hundred million dollars a year, and the first question the new team asked was small enough to fit on an index card: if we change the discount rules in Flow, what breaks?

It is a reasonable question. It is the kind of question you ask on day one, before you’ve earned the right to ask anything harder, the way you tap a frozen lake with your toe before you trust it with your weight. The team expected an afternoon’s answer. A diagram, maybe. A wiki page written by whoever set the rules up, slightly out of date but close enough.

What they got was three weeks.

Three weeks, because the discount logic did not live in one place. Some of it lived in Flow—not one automation but a thicket of them, forty-some triggers that fired off each other in an order nobody had drawn. Some of it lived inside apps: a promotions app that kept its own rules, a loyalty app that quietly overrode them at the cart, a bundling app that had opinions about both. Some of it lived in a Checkout Blocks configuration that exactly two people had ever fully understood, and one of those two people now worked somewhere else, and answered the recruiter’s “any chance you remember—” email the way anyone answers that email, which is to say warmly and uselessly.

So the team did the only thing left to do. They reverse-engineered their own store. They opened apps and read settings. They exported Flow definitions and laid them end to end on a wall. They placed test orders with fake discount codes and watched what came out the other side, like physicists inferring a particle from the wreckage it leaves. After three weeks they had an answer, and the answer was a forty-page document, and the document’s real finding was not here is how discounts work. The real finding was: nobody knew how discounts worked, and nobody had known for a while, and the store had been running anyway, the way a body runs a fever it hasn’t noticed yet.

A wall of brass hooks with dozens of tangled threads crossing and knotting in the center, no single strand traceable from end to end.
The discount rules. All forty-something of them. Somewhere in there.

This is the part everybody gets wrong about leaving Magento. The brand had left Magento precisely to escape this—the custom PHP nobody could read, the cron jobs that ran for reasons lost to staff turnover, the plugin some contractor wrote in 2017 that you couldn’t remove because something, somewhere, still leaned on it. Shopify was supposed to be the cure. And in one narrow sense it was: the PHP really is gone. The cron jobs really are gone. Nobody is afraid of the database anymore.

But business logic does not evaporate when you change platforms. It has to live somewhere. It always has to live somewhere. On Magento it lived in code, which was frightening but at least located—there was a repository, and the logic was in it, and a brave engineer with a weekend could read the whole thing. On Shopify the same logic scatters. A little into apps. A little into Flow. A little into Checkout Blocks. A little into Functions. Each piece is easier to install than the Magento equivalent ever was—you click a button, you toggle a setting, you never open a terminal. And each piece is, individually, simpler. But they do not add up to something simpler. They add up to the forty-page document and the three lost weeks.

The complexity didn’t disappear when they left Magento. It migrated somewhere more colorful.


We want to be careful here, because there is a version of this chapter that reads as apps are bad, and that version is wrong, and you would be right to stop reading if we wrote it. Apps are how Shopify works. The ecosystem is the platform’s great advantage over every bespoke stack you could build instead; the fact that a subscription engine or a returns portal or a tax calculator is a fifteen-minute install rather than a six-month build is not a trap, it’s a gift, and brands that refuse the gift out of purity end up rebuilding the commerce equivalent of the wheel, badly, on a deadline.

The argument is narrower and meaner than apps are bad. The argument is this: faster to install and easier to reason about are not the same thing, and at a certain scale they stop being the same thing rather violently. At a small store they’re close enough that the difference doesn’t bill you. You install ten apps, you set them up, you can hold the whole arrangement in your head, and if something breaks you know roughly where to look. At a hundred million dollars of GMV and up, the gap opens. The number of apps grows. The interactions between them grow faster than the apps do—that’s the cruelty of it, the connections multiply quadratically while the things being connected only add up—and the day arrives when no single person can answer if we change the discount rules, what breaks, and the only honest answer is let’s find out, which costs three weeks.

Which is to say: at scale, your app strategy is not a procurement question. It’s a governance question wearing a procurement question’s clothes. You think you are deciding which subscription app. You are actually deciding where will this part of our business live, who will own it, and will anyone be able to find it in two years. The brands that do this well are not the brands that installed the fewest apps. We’ve seen ascetic stores that were nightmares and sprawling ones that were pristine. The brands that do this well are the ones that always knew where everything was.


There are three ways the colorful complexity bills you, and they’re worth taking slowly, because each one is invisible at the size where you make the decision and expensive at the size where you live with it.

The first is data fragmentation. Every app you install is, quietly, its own little database. The subscription app keeps its subscription records—not in your customer object, in its store, mirrored back to you through whatever fields it chooses to expose. The loyalty app keeps its points ledger. The reviews app keeps its reviews; the recommendation app keeps its index; the wishlist app keeps, in at least one true story we will not stop telling, the wrong product variants for three months. At low volume this is fine, the way a messy desk is fine in a small office. At scale it is three problems stacked on top of each other. It’s a migration problem, because the day you want to leave that app—and you will want to leave some app, eventually, every brand does—the data you need is shaped the way the vendor found convenient, not the way you’d have shaped it, and getting it out is an archaeology project. It’s a reporting problem, because the truth about your customers is now smeared across a dozen systems and no single query touches all of it. And it’s a compliance problem, because when a customer in the right jurisdiction exercises their right to be forgotten, you are now responsible for finding them inside every one of those little databases, and you cannot delete a record you don’t know exists.

The second is pricing. App pricing is almost always a function of volume—orders, or GMV, or active subscribers, some meter that ticks up with your success. On the demo it’s nothing. On the demo it is so obviously nothing that bringing it up feels small, like checking the price of bread. And then your business does the thing you started the migration in order to let it do, which is grow, and the meter ticks, and at two hundred million dollars of GMV the app that cost a rounding error at the demo now costs more annually than building and maintaining the equivalent yourself. The difference—and this is the part that should sting—is that you have been paying all that money to rent. When you build, the build is yours; the maintenance is a cost but the asset is on your side of the ledger. When you rent, you pay ongoing rent for infrastructure you cannot modify, and at the end of every year you own exactly nothing, and the meter is higher than it was. We are not saying never rent. We rent constantly. We are saying: know the number you’ll be paying at twice your current size, because that’s the number that matters, and the demo will not show it to you. Run the math at 2× your current size, not your current size. Write it on something. You’ll want it again.

The third is the subtlest and the one that separates the brands that age well from the brands that calcify. Call it the primitives gap. Shopify has native concepts—metafields, Markets, B2B, Checkout Extensions, the new customer accounts, Functions. These are the platform’s grammar. Some apps are built in that grammar: they store their data in metafields you can read, they extend the native checkout rather than replacing it, they treat Shopify’s concepts as the foundation and add a floor on top. Other apps bring their own everything—their own data model, their own configuration surface, their own front-end logic bolted onto your storefront—and treat Shopify as a billing relationship and a place to live. The first kind compounds in value. Because it speaks the platform’s language, it interoperates with the next app that also speaks it, and it inherits each new platform capability roughly for free. The second kind compounds in debt. It creates a parallel system—its data, its config, its UI—that is not fully visible to anything else, including you, and that has to be reconciled by hand at every boundary.

This gives you a test, and it’s the one we want you to carry out of this chapter and into the rest of the book, because we are going to lean on it again and again: does this app build on Shopify’s native concepts, or does it introduce its own layer? That single question predicts more about how an app will age than its review count, its pricing tier, or the confidence of the salesperson demoing it. An app like Shoplift, which works through the platform rather than around it—building on the native primitives instead of shadowing them—earns its place the easy way; the longer you run it, the more it’s worth, because it grows as the platform grows. An app that reinvents what Shopify already gives you costs you a little more each quarter as the two systems drift, and someday the drift is a forty-page document and three lost weeks.

Two similar plants on a workbench: one growing through a trellis rooted in its own soil, one wrapped around a freestanding wire armature set beside but separate from the pot.
Both green. One of them will need reconciling by hand at every boundary.

So: the primitives test first, before anything else. And only after an app passes it do the other questions earn their turn—the quality of its API and how much of your own data it’ll actually let you reach; whether its pricing stays sane at twice your size; the company behind it, whether they’ll exist and answer the phone in three years; and whether it’s compatible with the specific Shopify features you’ve decided to build your business on. Good questions, all of them. But they’re the second round. An app that fails the primitives test can have a beautiful API and friendly pricing and a wonderful team and it will still quietly build you a parallel world, and you will still be the one reconciling it at the boundaries forever.


If apps and Flow are where logic can live, the live question is when it should stop living there and become something you build. We get asked this constantly, usually phrased as should we build or buy, which is the wrong frame because it sounds like a one-time fork in the road when it’s really a thing that comes due over time. The honest pattern is almost always the same. A brand starts with an app, because starting with an app is correct—you do not build a subscription engine from scratch to test whether subscriptions work for you, you install one and find out. The app serves well. Then the domain grows. Two years in, subscriptions are not a feature anymore, they’re a third of the revenue, and the brand’s needs have outrun what the app was built to do—and the app pricing has outrun what the brand wants to pay—and the data the app holds has become too important to leave in someone else’s database. So the brand extracts it. Builds the custom thing. Not because buying was a mistake; buying was right for the years it was right. Because the brand grew into a different decision. Subscriptions is the canonical example, but the shape repeats everywhere: the right tool at one size is the wrong tool at the next, and the brands that suffer are the ones who mistook the first decision for a permanent one.

There are three signals that the day has come, and you usually feel at least one of them before you can name it. The first is the math—the one you already wrote down—when app pricing at your actual volume, run forward to twice your size, exceeds what it would cost to build the thing and keep it running. The second is complexity: you find yourself fighting the tool, writing workarounds for its limitations, filing feature requests and waiting on a roadmap you don’t control, every new Shopify capability becoming a negotiation with the vendor about when, or whether, they’ll support it. The third is ownership: the data has become compliance-relevant, or portability-relevant, or central to reporting in a way that makes its living in a vendor’s store an actual liability rather than a theoretical one. One signal is a conversation. Two is a plan. Three and you are already late, and the only question is whether you extract on your schedule or the vendor’s.

A tideline of small debris—rope, shells, a spool—curving across sand, with a pair of bare feet standing just behind it on the dry side.
Natural sediment of a platform that makes every individual decision easy and no individual decision visible.

None of this requires you to install fewer apps. We keep saying that because it’s the instinct everyone reaches for first—the answer is restraint, the answer is a smaller stack—and it’s not the answer. The brand with ten apps and no map is in more trouble than the brand with forty apps and a clear one. The discipline is not subtraction. It’s a single question, asked before every app, every Flow, every Checkout Blocks toggle, every Function—asked early, while it’s still cheap to answer, instead of three years later when it costs three weeks: where will this logic live, and who will own it in two years?

If you can answer that, install the app. Build the Flow. Toggle the thing. The answer being “in this app, owned by the ops team, and that’s fine” is a perfectly good answer—most of the time it’s the right one. The danger was never the apps. The danger is the answer being a shrug.

And to the one of you reading this with a particular cold feeling in the stomach—the head of digital who approved an app last quarter, the engineer who built the eleventh Flow on a Friday because it was faster than the meeting it would have taken to do it properly—you are not in trouble. Everybody’s store has some of this in it. Ours did. The forty-page document is not a verdict on your competence; it’s the natural sediment of a platform that makes every individual decision easy and no individual decision visible. You don’t have to dig the whole thing out this week. You have to stop adding to the pile blind. Go find out where one thing lives. Just one. Then ask who’ll own it in two years. The map gets drawn the same way it got lost—one decision at a time—except this time someone’s holding the pen.