GET A FREE STORE AUDITFREE AUDIT

OCT 6, 2026 · 8 MIN READ

Technical debt in a Shopify theme, quantified

"The theme is a mess" never gets a budget. A number does. Five cheap, repeatable proxies turn a vibe into a figure a business can actually approve work against.

A hand placing a teal card onto a gridded layout sheet, with folders labeled TEMPLATE and SECTION and colored cards beside it

Measure it as a small set of counted proxies, tracked over time, rather than a single score. Five are cheap enough to produce from tools that already exist: Theme Check issues by severity, the share of snippets and assigns that are provably dead, the share of templates still on vintage .liquid rather than JSON, how often an asset or script check fails its budget, and how concentrated the blast radius is, meaning how many files a change to one snippet can reach. None of these is technical debt itself. Each is a number that moves in the direction debt moves, is free to re-run monthly, and (unlike a single "debt score" from a paid tool) can be explained to a non-technical stakeholder in one sentence. Attach an hours-to-fix estimate to each proxy and the audit becomes a budget line instead of a complaint.

IN SHORT

  • A single "technical debt score" cannot be interrogated by the person approving the budget; five named, counted proxies can, because each one is a sentence rather than a vibe.
  • Theme Check already produces the cheapest of the five: run it and track error and warning counts by check, by month, rather than treating a clean run as the goal.
  • OrphanedSnippet and UnusedAssign hits, expressed as a share of total snippets and assigns, are a defensible proxy for how much of a theme nobody currently understands.
  • The share of templates still on vintage .liquid files rather than Online Store 2.0 JSON templates is a binary, checkable migration-debt signal with no tooling required to measure it.
  • AssetSizeCSS, AssetSizeJavascript, ParserBlockingScript and RemoteAsset failures are a direct proxy for load-time debt, and Theme Check reports all four for free.
  • Blast radius (how many templates a single snippet reaches) is worth counting for the ten or fifteen most-included files; a change to one of them costs more to review regardless of its own line count.
  • A debt figure is only fundable once it is converted to hours: multiply each proxy by what fixing one instance of it actually takes, and the audit becomes a budget line rather than an opinion.

Why "the theme is a mess" never gets funded

Every merchant with a theme old enough to have opinions about it has heard some version of "this needs a clean-up." It is almost never followed by a budget, and the reason is not that the complaint is wrong. It is that nobody approving spend can act on a feeling.

A number changes that, but only if it survives the obvious follow-up question: how did you get it? A single proprietary "technical debt score" fails that test immediately, because the answer is "a formula we cannot show you." A count of specific, named things (how many orphaned snippets, how many templates still on the old architecture, how many assets over budget) survives it, because each one is a sentence a non-technical stakeholder can repeat back correctly.

So the exercise below is not a single metric. It is five, chosen because each is cheap enough to re-run every month and concrete enough to argue about.

Proxy one: what the linter already counts

Theme Check is Shopify's own linter for the Liquid and JSON in a theme, and running it costs nothing. It already exists, and most themes have never had someone read its full output rather than fixing whatever broke a specific build.

Track two numbers from it monthly rather than treating "zero issues" as the goal: total issues by severity, and the trend. A theme with 40 warnings that was at 65 last quarter is improving. A theme with 12 warnings that was at 4 last quarter is not fine because the absolute number is small. It is accumulating, and the trend is the thing worth showing whoever approves engineering time.

Two checks are the highest-value proxies inside this one. OrphanedSnippet counts files that exist but render nowhere, and UnusedAssign counts variables nothing reads. Both are close to a direct count of code nobody can currently explain the purpose of. Express each as a share of the theme's total snippet or assign count, not a raw number, so a small theme and a large one are comparable on the same scale.

Theme Check is Shopify's own linter for the Liquid and JSON in a theme, and running it costs nothing.
Prakash Prabhakar

Proxy two: how much of the theme is still on the old architecture

Online Store 2.0 gives a theme sections on every template, blocks inside sections, and settings at both levels: the architecture that lets a merchandiser build a page without a developer. A theme built or extended before that shift, or one where new templates keep getting added as plain .liquid files out of habit, is carrying a specific, checkable form of debt: pages that require a deploy to change something a JSON template would let a merchandiser edit directly.

This proxy needs no tool. Count templates in templates/ that are .liquid rather than .json, as a share of the total. A theme at 90% JSON with three legacy checkout-adjacent templates left over is a small, scoped migration. A theme still mostly .liquid is not a clean-up. It is the theme rebuild that the refactoring conversation eventually has to admit to.

Proxy three: how often the load-time budget is breached

Theme Check reports this directly, and it is the proxy most directly tied to a number a business already tracks: page speed. AssetSizeCSS and AssetSizeJavascript fail when a file exceeds a configured size threshold. ParserBlockingScript flags script tags without defer or async. RemoteAsset flags assets pulled from third-party domains instead of Shopify's own CDN.

Count failures across these four checks the same way as proxy one: by severity, by month, as a trend rather than a one-off pass or fail. Unlike the first two proxies, this one has a direct line to a metric the business already watches, which makes it the easiest of the five to get budget approval against: "fourteen scripts are shipping unminified or blocking parse" is a sentence a CRO stakeholder understands without translation.

Proxy four: blast radius, for the files that matter

The first three proxies count issues. This one counts risk, and it does not need every file measured, only the ten or fifteen most-included snippets and sections, which is usually where a theme's real fragility lives.

For each, grep the theme for every template and snippet that renders it. A snippet included from one template is a contained risk regardless of how untidy its code is. A snippet included from eleven templates, including ones nobody has opened since the last migration, is a standing liability that a three-line change can turn into an incident, and it is exactly the kind of debt a line-count-based review misses, because the diff looks small.

Record the count next to each file's name and revisit it after any restructuring work. A successful consolidation should reduce the number of high-blast-radius files, not just the number of lines in them.

Turning five numbers into a budget line

None of the above is technical debt by itself, and presenting five counts to whoever approves spend will not get the work approved either. It will get the same shrug as the original vibe, with more precision attached to it.

The conversion that works is hours. Estimate, from the last time your team actually did each kind of fix, how long resolving one instance takes: an orphaned snippet is minutes; a vintage-to-JSON template migration is hours per template; a blast-radius consolidation is a scoped project with its own estimate. Multiply each proxy by its per-instance cost and the five numbers become one figure with a currency sign in front of it, which is the artifact that actually gets a "yes."

Re-measure on the same schedule the figure was approved against (monthly is usually right for a trading store) and report the trend, not just the latest snapshot. A stakeholder who approved three months of clean-up wants to see the count falling; a single audit with no follow-up measurement is indistinguishable, from where they sit, from money that disappeared.

What we would not do

Buy a single proprietary "debt score" from a tool that will not show its formula. If a number cannot be explained in one sentence to the person approving the spend, it will not survive the meeting where the spend gets decided.

Grade every theme against theme-check:all, the strictest preset, and report the resulting gap as "the debt." As covered in refactoring a theme without a redesign budget, a gate set at the standard you aspire to just produces a permanently large number nobody acts on; measure against the baseline the theme already passes, and track movement from there.

Commission a full rewrite from one high total. The five proxies above are diagnostic, not a verdict: a theme can be high on proxy two (vintage templates) and low on everything else, which is a scoped migration, not a rebuild. Only recommend a rebuild when the numbers say most of the theme is affected across more than one proxy at once.

Questions this raises

How do you measure technical debt in a Shopify theme?

As a small set of counted proxies rather than one score: Theme Check issues by severity and trend, the share of snippets and assigns that are provably dead (`OrphanedSnippet`, `UnusedAssign`), the share of templates still on vintage `.liquid` files instead of Online Store 2.0 JSON templates, how often asset and script budgets fail, and the blast radius of the ten or fifteen most-included files. Each is cheap to re-run monthly and specific enough to explain in one sentence.

Is running Theme Check enough to measure technical debt?

It covers three of the five useful proxies (dead code, asset-size failures and parser-blocking scripts) for free, which makes it the cheapest place to start. It does not see architecture (how much of the theme is still vintage `.liquid`) or blast radius (how many templates a given snippet reaches), so treat a clean Theme Check run as one input, not the whole measurement.

What's the difference between technical debt and an outdated theme?

Outdated usually means architectural: still substantially on vintage `.liquid` templates rather than Online Store 2.0's sections-everywhere model, which is proxy two above and generally the most expensive to fix. Technical debt is broader: dead code, budget-breaching assets and concentrated blast radius all count, and a theme can carry a lot of it while being fully on the current architecture.

How do you turn a technical debt audit into a budget the business will approve?

Convert each proxy into hours, using how long your team has actually taken to fix that kind of issue before, then multiply by the count. Five abstract numbers become one figure with a cost attached, which is what gets approved: a list of issues, however accurate, reads as an opinion rather than a budget line.

Should every theme be measured against the strictest Theme Check preset?

No. Measure against the baseline the theme currently passes and track whether the count is falling, the same advice that applies to using Theme Check as a merge gate. Grading everything against `theme-check:all` produces a large, unmoving number that does not tell anyone whether the current quarter's work helped.

How often should a theme's debt be re-measured?

On the same cadence the budget was approved against. Monthly is usually right for a store that trades continuously. Report the trend against the previous measurement, not just the current snapshot; a stakeholder who approved clean-up work is checking whether the number moved, not what it currently is.

General information, not legal, tax or financial advice. Rates, limits and deadlines come from the vendors and authorities named, and they change: check the linked source before relying on one.

PART OF OUR SERVICE

Build a Shopify store worth the traffic you send it

New stores, themes and design-to-Shopify builds

EXPLORE BUILD →

NEXT STEP

Free store audit

A senior Shopify engineer reviews your storefront, theme performance and checkout, then sends a prioritized list of fixes.

A hand gestures towards a small shop doorway tied with colorful ribbons, with a tablet on a workbench inside