3,000-line God Object (Shop model)⟶Strangler-Fig-extracted domains
Shopify's Shop model had grown past 3,000 lines into a God Object. Instead of a risky big-bang rewrite, they grew a new system over the old one and let the legacy code get strangled away.
You don't demolish the load-bearing class. You grow its replacement around it until the original can be pulled out.
Inside Shopify’s Rails codebase, the Shop model had grown to more than 3,000 lines of code — a classic God Object, a single class holding far more responsibility than any one class should. Shopify’s Kernel Architecture Patterns team took on the job of breaking it up.
The concrete example they walk through is small on purpose: extracting the store settings tied to Shopify Capital, specifically a locked_settings attribute, out of the Shop model and into its own home.
COMPLICATION
Why you can't just rewrite it
A class this central is load-bearing. Code across the whole application reads from and writes to it, so any attempt to replace it wholesale is a high-risk, all-at-once change to something the live system depends on continuously.
To even find the worst offenders, Shopify leaned on the Flog metric, which scores code by ABC complexity — assignments, branches, and calls — to point at the areas most in need of refactoring.
QUESTION
How do you replace a live system without turning it off?
So here is the question the pattern answers. How do you refactor something the application uses constantly — reading and writing, in production, all day — into a cleaner design, without a maintenance window, without a risky cutover, and without losing data along the way?
ANSWER
Grow the new system over the old one
The answer is the Strangler Fig pattern, named after Martin Fowler’s writing: a new system slowly grows over top of an old system until the old system is “strangled” and can simply be removed. Shopify applies it in seven steps. Define an interface for the new system; replace the old calls with that interface; create a new data source; write to both the old and new sources at once; backfill the new source from the legacy data; switch readers over to the new source; then remove the legacy code and stop writing to the old source.
The safety lives in the details. Writes to both sources are transactional so the two stay in sync, backfill uses pessimistic locking to stay consistent under concurrent updates, and the data migration runs on Shopify’s open-source Job Iteration API so it can move at scale without losing its place. Business logic goes into plain Ruby objects, kept separate from the persistence infrastructure.
TAKEAWAY
Incremental beats heroic
By extracting locked_settings this way, Shopify chipped a well-defined piece off a 3,000-line God Object while the application kept serving traffic and monitoring stayed green throughout. The same seven steps then apply to the next responsibility, and the next.
The transferable idea isn’t the specific tooling — it’s the shape of the move: replace a system in slices, keeping both alive until the new one has fully taken over.
The safest way to remove a load-bearing system is never to remove it — it’s to grow its replacement around it until, one day, there’s nothing left for the old one to hold up.
The techniques for pulling a domain out of the same monolith these boundaries are meant to protect.
A plain-language, AI-drafted and human-edited retelling of the article published on shopify.engineering, reorganized and explained in our own structure and words, with original analysis in the editor's note above. The facts, numbers, and decisions belong to the original author and are not altered. For the full depth, read the source.