How Many Shopify Apps Is Too Many? I Measured It

Everyone says apps slow your store down. Almost nobody says by how much. Here are measurements from real stores and a method for auditing your own.

Share
How Many Shopify Apps Is Too Many? I Measured It. Abstract shopify illustration in orange and dark grey on debugly.dev

Disclosure: I spent four years building Shopify themes at Debutify, finishing as CDO. Theme companies have an incentive to blame apps for slow stores, so treat the framing with appropriate suspicion and check the method, which I have written out so you can run it yourself.

The short answer

There is no magic number. The count does not matter, the payload and main thread time do.

From auditing merchant stores, the rough picture:

Apps installed Typical added JS Typical mobile Lighthouse
0 0 KB 88 to 96
1 to 3 lean apps 80 to 200 KB 75 to 88
4 to 7 typical apps 300 to 600 KB 50 to 70
8 or more 700 KB to 1.4 MB 28 to 50

But the spread within each row is enormous. I have seen a store with twelve apps outperform a store with four, because the twelve were well built and loaded lazily while the four included two chat widgets and a session recorder.

Measure yours rather than counting.

Why app count is the wrong metric

Apps differ by more than an order of magnitude in cost. A well built app that loads 12KB on product pages only is not comparable to one that loads 240KB of framework on every page including the cart.

What actually determines the cost:

Payload size is the obvious one and the least important of the three.

Main thread time matters more. A 200KB script that parses and executes for 400ms on a mid range Android phone is much worse than a 300KB script that runs in 40ms. Interaction to Next Paint is a Core Web Vital and main thread blocking is what breaks it.

Load timing matters most. A script loaded with defer after first paint costs you almost nothing in LCP. The same script loaded synchronously in the head blocks rendering entirely.

Number of extra connections. Each new third party origin means a DNS lookup, a TCP handshake, and a TLS negotiation before a single byte of the script arrives. On a mobile connection with 150ms of latency, five new origins is close to a second of overhead before any script has been parsed.

That last one is genuinely underrated. Two apps served from the same CDN are meaningfully cheaper than two apps on separate domains.

How to measure your own store

The method that produces numbers you can act on. Budget an afternoon.

Set a baseline

Duplicate your live theme. In the duplicate, disable every app embed and comment out every app script tag you can find in theme.liquid. Run PageSpeed Insights on a product page. That is your theme's actual score with no apps.

Most merchants are surprised here. If your baseline is 90 and your live store is 38, the conversation about performance is entirely a conversation about apps.

Measure each app individually

Re enable one app. Run PageSpeed Insights on the same URL. Record the score, the LCP, the Total Blocking Time, and the transferred JavaScript. Disable it. Move to the next.

Run each measurement three times and take the median, because PageSpeed Insights results vary by several points between runs and a single measurement will mislead you.

You end up with a table like this, which is from a real store I audited with names generalised:

App Added JS Added TBT Score delta
Live chat 218 KB 410 ms -14
Reviews 96 KB 120 ms -5
Upsell and bundles 141 KB 260 ms -9
Email capture popup 74 KB 90 ms -4
Session recording 89 KB 180 ms -6
Loyalty 62 KB 70 ms -3
Currency converter 31 KB 40 ms -2
Wishlist 48 KB 60 ms -2

Baseline 91, live store 47. The deltas do not sum exactly to the difference because contention on the main thread is not additive, but the ranking is what you need.

Now ask the business question

For each app, what is it worth?

The live chat cost fourteen points. It handled eleven conversations a week. The merchant's own data showed an average of 2,400 mobile sessions a week on product pages. Fourteen Lighthouse points on mobile, mostly from main thread blocking, against eleven conversations.

We did not remove it. We changed it to load on interaction, which is covered below, and recovered eleven of the fourteen points while keeping the functionality. That is usually the right answer, and it is available far more often than merchants realise.

The session recording tool had been running for two years. It was installed for a specific investigation that concluded in 2024. Nobody had opened it in eighteen months. That one we removed.

The patterns worth fixing

Load on interaction rather than on load

The single highest leverage change, and it applies to chat widgets, wishlist tools, and anything else the visitor has to act on before they need it.

<script>
  const loadWidget = () => {
    if (window.__widgetLoaded) return;
    window.__widgetLoaded = true;
    const s = document.createElement('script');
    s.src = 'https://widget.example.com/app.js';
    s.async = true;
    document.body.appendChild(s);
  };

  ['pointerdown', 'keydown', 'touchstart', 'scroll'].forEach(evt =>
    window.addEventListener(evt, loadWidget, { once: true, passive: true })
  );

  setTimeout(loadWidget, 8000);
</script>

The widget is ready long before any human reaches for it, and it is entirely absent from your critical path. I have moved stores ten to fifteen points with this pattern alone.

The timeout fallback matters. Without it, a visitor who reads without scrolling never gets the widget, and if it is a support channel that is a real cost.

Restrict apps to the pages that need them

Most apps load everywhere by default. A review widget does not need to run on the cart page. A currency converter does not need to run in the checkout.

If the app injects through your theme:

{%- if template.name == 'product' -%}
  {% render 'reviews-app' %}
{%- endif -%}

If it injects through an app embed, check the app's settings for page restrictions. Many have them and merchants rarely look.

Remove residue from uninstalled apps

Genuinely common and pure waste. Uninstalling an app in admin does not always remove its script tag, its app embed toggle, or the snippet it added to your theme.

After any uninstall, search your theme for the app's name, check the App embeds panel for a leftover toggle, and look in your snippets directory for orphans.

I audited a store loading 340KB from four apps that had all been uninstalled. Nobody had checked, because uninstalling felt like it should be enough.

Audit your tag manager separately

Google Tag Manager is one script in your Network tab and potentially fourteen scripts in practice. Everything inside the container loads at runtime and is invisible in your theme code.

Open GTM, list the tags firing on page load, and ask the same question about each. Marketing pixels accumulate the same way apps do and nobody removes them either.

Consolidate where you can

Two apps from the same vendor often share a bundle. Five apps from five vendors means five origins and five connection setups. When choosing between apps, a suite that covers three of your needs from one origin can be meaningfully faster than three best of breed tools, even if each individual tool is better.

This is a real tradeoff and I am not claiming the suite is always right. But connection overhead should be in the decision, and it usually is not.

What good looks like

A store I worked with went from 47 to 78 on mobile with no functionality removed at all:

  • Chat widget moved to load on interaction, recovering 11 points
  • Reviews restricted to product pages, recovering 3
  • Session recorder removed, since it was genuinely unused, recovering 6
  • Upsell app's own lazy load setting enabled, which was already available and switched off, recovering 5
  • Two uninstalled apps' residual scripts removed, recovering 4
  • LCP image set to eager with fetchpriority high, recovering 4

Total time spent: about six hours including measurement. Nothing was rebuilt and no app the merchant valued was removed.

That last point matters. The framing "apps are bad, remove them" is unhelpful, because merchants install apps for reasons and those reasons are usually revenue. The useful framing is that most apps are configured badly by default, and fixing the configuration recovers most of the cost.

When an app genuinely has to go

Sometimes the numbers do not work.

An app costing you fifteen points on mobile, used by a fraction of a percent of visitors, providing something you could achieve with a link, should go. So should anything whose value nobody in the business can articulate, which is more common than you would expect once you actually ask.

Bring the table. "This app costs us fourteen Lighthouse points and handles eleven conversations a week" is a conversation that can reach a decision. "Apps are slowing us down" is not.