Skip to content

Development

A performance budget for Shopify themes

Agree the byte, request and Core Web Vitals numbers a Shopify theme may not exceed, then enforce them on every release and app install.

By CartKernel · Published

A performance budget is a short list of numbers a theme is not allowed to exceed, agreed before anyone writes code and checked before anything ships. It turns speed from an occasional cleanup project into a constraint the store lives inside. Without one, every gain from a rebuild is spent again by the next app install, and nobody can point to the moment it happened.

The budget below is a shape, not a prescription. Set your own numbers from your own field data, write them into the theme repository, and make exceeding them a decision somebody signs rather than an accident.

Write the budget as numbers somebody can fail

A budget has three parts: outcome metrics that describe what shoppers feel, resource limits that predict those metrics, and a rule for what happens when a change goes over.

Budget line Example limit Measured where
Largest Contentful Paint, mobile, 75th percentile 2.5 seconds Field data over the last 28 days
Interaction to Next Paint, mobile, 75th percentile 200 milliseconds Field data over the last 28 days
Cumulative Layout Shift, mobile, 75th percentile 0.1 Field data over the last 28 days
Compressed JavaScript, product template A fixed kilobyte ceiling you set from today’s number Lab test on a throttled mobile profile
Third-party origins requested before first paint A small fixed count Lab test, network panel
Web fonts loaded Two files, one family, two weights Theme code review
Images above the fold One priority image, everything else deferred Theme code review

The resource limits are the useful half. Outcome metrics move slowly and lag deployment by weeks because they come from real visits. Bytes and request counts can be measured on a branch in a minute, which is the only way a budget can gate a release.

Take the outcome numbers from field data, not from a lab score

Lab tools run one simulated visit on one connection. Your budget has to be defended against real devices in real places, so the outcome half of the budget is set and judged on field data at the 75th percentile for mobile. Lab runs are for diagnosis: they tell you which request delayed the hero image, not whether shoppers are having a slow time.

Two practical consequences. First, judge a release two to four weeks after it ships, when enough visits have accumulated. Second, keep a lab measurement of the same templates on a fixed device profile so you can compare a branch with production on the same day. The Core Web Vitals checker gives you the current field numbers per template to set the starting line, and the Core Web Vitals entry defines each metric.

Budget per template, because templates are what change

A single site-wide number hides the pages that matter. Shopify themes are built as templates, apps are installed against specific templates, and the work is always template-scoped. Give each of these its own line:

  • Home. Usually the heaviest hero media and the most marketing scripts.
  • Collection. Many images, filters, and often infinite scroll or a facet widget.
  • Product. Galleries, reviews, upsells, size guides, subscription widgets, sticky bars.
  • Cart and cart drawer. Interaction-heavy, so this is where interaction to next paint is won or lost.
  • Search results. Frequently powered by a third-party script with its own bundle.

Product and collection templates carry most of the sessions on a catalog site, so they get the tightest limits. A generous home page budget is defensible if the home page is a small share of entries.

Decide in advance where the bytes are allowed to go

Most of a theme’s weight comes from a short list of recurring choices. Naming them in the budget document removes the argument later.

  1. One JavaScript entry point per template. Anything a shopper cannot see or touch in the first viewport loads after interaction or on intersection.
  2. A capped number of blocking third-party origins. Every extra origin adds a DNS lookup, a connection and a handshake before a byte of content arrives.
  3. Fonts, fixed. Two weights, subset to the character range you actually publish, served with a swap behavior so text renders immediately.
  4. Images with intrinsic dimensions everywhere. Width and height attributes or a CSS aspect ratio on every image and video slot.
  5. A single source of truth for tracking. One tag container, one measurement plan, no duplicate pixels added by individual apps.
  6. Liquid work bounded. Loops over large collections inside a section render on the server every request. Cap the loop size and cache fragments where the theme allows.

App installs are the most common way a budget gets broken, because an app can inject script tags into every page from outside the theme. Treat an install as a code change: measure the templates before and after, record the delta, and keep the number where the team can see it. The trade-offs are covered in how many apps are too many on a Shopify store.

Enforce it in the release process, not in a meeting

A budget that lives in a document is a wish. Make it a gate:

  1. Add a lab performance run to the branch preview so every pull request reports the same numbers on the same profile.
  2. Put the current budget in the repository next to the theme code and update it in the same commit that changes it.
  3. Require the person requesting an exception to say which line they are exceeding, by how much, and what they will remove to pay for it.
  4. Review field data monthly against the outcome lines and log the result. A drift of a few percent is noise. A step change has a cause, and the deploy log will name it.
  5. Give one person the authority to decline an install. Speed decisions distributed across a whole team default to yes.

Paying for a new feature

When a request exceeds the budget there are three honest answers, and choosing one openly is the point of the exercise.

  • Make room. Remove or replace something of similar weight. A review widget rendered server-side can fund a new gallery.
  • Defer the cost. Load the feature after the first interaction, on scroll, or only on the template that needs it. Most sitewide scripts are needed on one template.
  • Decline. The feature is worth less than the traffic it costs. Write down the reasoning so the request does not come back every quarter.

An illustrative example of the third path: say a store measures its product template at a fixed JavaScript ceiling and a proposed widget adds a third of that ceiling again on every page view. If the widget serves a feature used by a small fraction of visitors, the cheaper build is a link that loads the widget on demand.

What a budget does not fix

A budget constrains the theme. It does not fix a slow origin response, an oversized image pipeline, or a checkout you do not control. If field data shows a slow start before any theme code runs, the problem is upstream and belongs in site speed optimization rather than in the theme. If the numbers are already failing on mobile before you begin, Shopify store slow on mobile walks the diagnosis in order, and the mobile product page teardown covers what to cut on the template that matters most.

Set the budget from where you are today, not from an aspiration. A store whose product template currently loads well above a sensible ceiling should write today’s number down, then ratchet it in stages. A limit that is failed on day one is ignored by week two.

A starting checklist

  • Pull 28 days of field data per template and record the three outcome numbers.
  • Run a lab test on a throttled mobile profile and record bytes, requests and third-party origins per template.
  • Write both sets of numbers into a budget file in the theme repository.
  • Add the lab run to branch previews and fail the check when a limit is exceeded.
  • Name the owner who approves exceptions and app installs.
  • Diary a monthly field review and a quarterly ratchet.

Theme work under a budget is slower to start and much cheaper to maintain, because the store stops relitigating the same decisions. If you want the budget set and enforced by the team building the theme, that is part of Shopify development.


Sources

Find the leak.

A free Growth Analysis ranks what your store should fix first, by revenue at stake.