Should You Hire a Shopify Speed Optimization Service, or Will an App Fix It?
A speed app can compress images, lazy-load below-the-fold content, and defer non-critical scripts — and that closes maybe a third of what's actually slowing a typical Shopify store. It cannot rewrite a Liquid loop fetching metafields nobody sees, cannot reduce the number of separately-loaded app scripts fighting for main-thread time, and cannot touch code baked into your theme.liquid. Here's the ten-minute diagnostic that tells you which category your store is actually in, before you spend $20/month or $2,000 finding out the hard way.
A Shopify speed app can compress your images, lazy-load what's below the fold, and defer scripts that don't need to run immediately — and for a lot of stores, that's genuinely most of the problem, solved for $20-50 a month. But an app cannot rewrite a Liquid loop that's fetching metafields for products nobody scrolled to, cannot reduce the number of separate third-party scripts fighting for main-thread time when you've got fifteen apps installed, and cannot touch code sitting directly in your theme's theme.liquid. Whether you need a service or an app depends entirely on which category your slowdown falls into, and you can find out which one in about ten minutes before spending money on either.
What a speed app can actually fix
Speed apps work almost exclusively at the content layer, through a theme app extension or an app embed block. That gives them real, legitimate leverage over a specific set of problems:
- Image weight. Re-encoding to WebP/AVIF, serving responsive
srcsetsizes, and lazy-loading images below the fold withloading="lazy". - Non-critical script timing. Wrapping third-party snippets so they load with
deferor after first interaction instead of blocking the initial render. - Font loading. Adding
font-display: swapand preloading the fonts actually used above the fold instead of the whole family. - Basic CSS/JS minification for assets the app itself controls.
None of this requires touching your theme's source files, which is exactly why it's app-safe: Shopify's app review guidelines steer app developers away from writing directly into section and template Liquid, because two apps editing the same file is how stores end up with a theme that silently breaks on the next update. That safety boundary is also the ceiling on what an app can do for you.
What no app can touch, on any plan
The most common Largest Contentful Paint and Interaction to Next Paint problems on Shopify stores live one layer below where apps are allowed to operate: in the theme code itself.
A collection page that renders like this is a real, common pattern on customized themes:
{% for product in collection.products %}
{% assign spec = product.metafields.custom.full_spec_sheet %}
{% assign related = product.metafields.custom.related_bundle %}
...
{% endfor %}
That loop fetches two metafields per product for every product on the page, whether or not the shopper ever scrolls past the fourth row. On a 48-product collection page, that's 96 metafield lookups executed server-side before the first byte goes out — and it shows up in a trace as slow Time to First Byte, which no client-side speed app can do anything about, because the delay happens before any of your page's HTML, CSS, or JS is even sent to the browser.
The second pattern an app can't fix is sheer app-stack weight. Deferring a script's execution doesn't make the script free — a deferred Klaviyo pixel, a Judge.me widget, a Recharge subscription bar, and a Gorgias chat launcher still each parse and execute at some point, and on a mid-range phone that's real main-thread contention that shows up as poor Interaction to Next Paint even after "optimization." A speed app can move that cost later in the timeline. It cannot make five apps' worth of JavaScript weigh less than five apps' worth of JavaScript.
The ten-minute diagnostic before you spend anything
Run this before buying an app subscription or a service engagement — it tells you which category you're actually in:
- Open your store in Chrome DevTools → Lighthouse, or run it through PageSpeed Insights, and look at "Reduce unused JavaScript" and "Minimize main-thread work." Check the domain each flagged resource loads from.
- If the flagged resources are mostly third-party domains (googletagmanager.com, klaviyo.com, judge.me, and similar) — that's app-stack weight. A speed app's deferral logic will genuinely help here, and it's worth trying one before anything else.
- If a flagged resource is your own theme's asset —
assets/theme.js, an inline<script>block intheme.liquid, or a large chunk of server-rendered HTML on a collection or product page — that's theme code, and no app reaches it. - Check your Shopify admin's own speed score under Online Store → Preferences, which shows a Lighthouse-based score against comparable stores. It's a useful second opinion, but it measures the same synthetic run as PageSpeed Insights, not the CrUX field data Google actually uses to rank you — worth knowing why those two numbers disagree in the first place.
- Count your Liquid loops. Search your theme's collection and product templates for
{% for %}tags that pull metafields or related-product data for every item in a list, not just the ones rendered. That pattern is invisible to Lighthouse's summary score but shows up directly as slow TTFB.
If step 2 dominates, an app is the right first purchase. If step 3 or step 5 shows up, you've found the ceiling an app cannot cross, and no amount of switching speed apps will move that number.
Reading the report without guessing
Lighthouse doesn't make you infer which category you're in — it labels it, if you open the right panel. Under "Reduce the impact of third-party code," Lighthouse lists a Third-party usage table that breaks out every external script by transfer size and main-thread blocking time, attributed to the actual vendor (Klaviyo, Judge.me, Meta Pixel, and so on). If that table is where most of your blocking time sits, that's the app-stack problem a speed app is built for. Separately, under "Avoid an excessive DOM size" and "Minimize main-thread work," look at what's not in the third-party table — first-party JavaScript execution and long tasks Lighthouse attributes to your own domain are the theme-code problem no app reaches, because that time is spent running code an app was never given permission to touch.
One more tell: Total Blocking Time that stays high even after a speed app is installed and its "optimizations" show green in its own dashboard. That's not the app failing — it's the app correctly reporting that it fixed everything within its reach, while the remaining blocking time belongs to code it can't see.
What a service does that an app structurally cannot
A speed optimization service — done properly, not as a rebrand of installing three apps for you — has write access to theme code that an app is deliberately kept away from. That buys three things no app can:
- Rewriting the Liquid itself. Replacing a full-collection metafield loop with pagination-aware fetching, or moving expensive lookups to only the products actually rendered.
- Consolidating the app stack. Actually removing redundant apps (two review apps, a slider nobody uses) instead of deferring all of them forever — you can see exactly which unused app scripts are still loading with a free store scan that reads which scripts fire from apps you no longer have installed.
- Fixing INP at the source by breaking up long JavaScript tasks in custom theme sections, which requires editing the section's own script, not wrapping a third-party tag.
None of that is exotic work, and it isn't cheap for the same reason a plumber replacing a pipe inside a wall costs more than a bottle of drain cleaner: it requires opening the thing up. That's also exactly why the Core Web Vitals remediation checklist we've published separately treats app-layer fixes and code-layer fixes as two different phases, not one continuous scale of "more optimization."
Who should stop at the app, and who shouldn't hire anyone yet
Skip the service entirely if your store runs a mostly-default theme, fewer than six installed apps, and your Lighthouse trace flags mostly third-party scripts rather than your own theme assets. That's the profile where a $20-50/month app closes most of the gap, and a $2,000+ engagement would be paying to hear "install an app," which you can do yourself this afternoon.
Go straight to a service, and skip trialing another app first, if you're on a heavily customized or agency-built theme, have ten or more installed apps, or your diagnostic keeps flagging your own theme assets instead of third-party ones no matter which speed app you try. At that point every additional app subscription is a recurring cost solving a problem it structurally cannot reach, and the honest comparison isn't "app vs. service" — it's "keep paying monthly for partial results, or pay once to fix the actual cause."
The real cost difference isn't the hourly rate, it's what the work touches. Installing a speed app is a same-afternoon change you can revert by uninstalling it. Rewriting a collection template's Liquid, or breaking up a long JavaScript task inside a custom section, means working on a duplicate theme, testing every page type that uses that template, and having a rollback plan before it goes live — because unlike an app, a bad Liquid edit can take a page down, not just fail to speed it up. That QA overhead, not the code itself, is most of what a proper engagement is pricing in, and it's also why "just have the app do it" and "have a developer rewrite it" aren't points on the same scale. Our own store speed optimization guide walks through the code-layer fixes in more depth once you've established that's actually where your problem lives.
The decision, in one pass
Run the Lighthouse trace before spending anything. Third-party domains dominating the flagged resources means try an app first — it's cheap and it's built for exactly that problem. Your own theme.liquid, section scripts, or uncontrolled Liquid loops showing up instead means an app was never going to fix it, no matter how many you try, and the money is better spent once on the code than monthly on a subscription that can't reach it. If you're not sure which camp you're in, our store scanner pulls your real Core Web Vitals field data and flags dead app scripts for free before you commit to either — and if the diagnosis points to a code-layer fix, that's a conversation worth having with someone who can actually open the theme.