The Shopify platform
Learn about the infrastructure that Shopify provides to make the online store, and your theme, faster.
Anchor to Shopify CDNShopify CDN
Shopify provides merchants with a world-class content delivery network (CDN) backed by Cloudflare. Using a CDN means that your online store loads quickly around the globe.
Files delivered through the Shopify CDN are minified and compressed automatically using Brotli and gzip, which reduces the size of the files the browser must download. Requests use HTTP/3 and TLS 1.3 to further enhance request performance and security.
Storefront asset URLs use a /cdn path on the domain that serves the page, for example /cdn/shop/files/hero.jpg for store files and /cdn/fonts/ for fonts from the Shopify font library. Same-origin URLs improve performance by maximizing connection reuse in the browser.
You don't need to hard-code the cdn.shopify.com domain in your theme. Reference assets with Liquid URL filters like asset_url and image_url, and Shopify renders the appropriate asset host for each request.
For guidance on taking full advantage of the CDN in your theme, see Serve assets from Shopify CDN.
Anchor to Short delays for images in your storeShort delays for images in your store
Using a CDN means that all of your online store images are cached on thousands of servers around the world. When you make changes to your images, Shopify informs the CDN that the images have changed. To do this, Shopify uses the asset_url filter, which automatically appends version numbers to all of the URLs that it generates. For example, a version number appended to the end of a URL might look like this: ?v=1384022871.
If you link to an image without using the asset_url filter and upload a new version of the same image, then the image on your online store might not change to the new version for a day or more.
Only specific query parameters are recognized for versioning. The supported format uses the v parameter for version (for example, ?v=1384022871). Query parameters that aren't on the allowlist, such as appending a raw timestamp value without the v= prefix or using arbitrary parameter names, won't bust the cache.
Only specific query parameters are recognized for versioning. The supported format uses the v parameter for version (for example, ?v=1384022871). Query parameters that aren't on the allowlist, such as appending a raw timestamp value without the v= prefix or using arbitrary parameter names, won't bust the cache.
Anchor to CSS syntax to ensure automatic updatesCSS syntax to ensure automatic updates
If you reference an image directly in your CSS, then the URL is static and won't carry the asset version that Shopify updates automatically.
To make sure that your images are automatically updated, change your CSS syntax to include the asset_url filter.
For example, if your CSS looks like this:
then change it to look like this:
Anchor to Server-side renderingServer-side rendering
Storefront Renderer (SFR) is a server-side renderer that handles storefront requests. SFR is dedicated to serving storefront requests as fast as possible.
The storefront renderer significantly improves performance for cache misses, which are cases where a page or other requested data isn't found in cache memory and has to be retrieved from other cache levels or from main memory.
Anchor to Streamed HTML responsesStreamed HTML responses
Shopify can send storefront HTML to the browser in two parts, and on most pages it does. The first part is your layout from the top of the document to {{ content_for_header }}. Shopify sends it as soon as it's rendered, while your template's sections are still rendering. The second part starts with the output of content_for_header and follows when rendering completes.
The browser starts working on the first part right away. It parses the <head>, requests every stylesheet, font, and script it finds there, and opens the connections those requests need. By the time the sections arrive, the resources the first paint depends on are downloading or already downloaded. Total rendering time doesn't change. The browser's work overlaps with Shopify's instead of waiting for it.
The saving is the time the browser used to spend idle between the first byte and the arrival of the sections. Stylesheets, fonts, and scripts in the first part download during that time instead of after it, so First Contentful Paint (FCP) and Largest Contentful Paint (LCP) come earlier. The saving is largest on pages with heavy section Liquid and a render-blocking stylesheet, which describes most product and collection pages.
Shopify streams eligible pages automatically and is expanding the set of pages that qualify. A page is eligible when:
- It renders from a JSON template. Pages rendered from
.liquidtemplates aren't streamed yet. Shopify is working on supporting them. - The layout contains
{{ content_for_header }}as a plain output tag: no filters, not inside another tag or a snippet, and not assigned to a variable first. {{ content_for_header }}sits inside<head>, and</head>comes after it.
Preview themes, the preview bar, and the theme editor aren't streamed. To see the effect, test on your live theme.
Early Hints work with streamed pages too. Once Shopify has served a page, later visits receive the preload hints before the HTML, whether or not the response is streamed. The first visit to a page right after you publish a change can arrive without them, so don't judge Early Hints from a single reload of a theme you just edited.
Anchor to What this means for your themeWhat this means for your theme
- On a streamed page, everything above
{{ content_for_header }}reaches the browser first. Put the stylesheets, font preloads, import map, and CSS variables that the first paint needs above it, and check the ordering dependencies before you move anything. See Load first-paint resources beforecontent_for_header. - Keep
{{ content_for_header }}inside<head>and leave it as it is. A wrapped, filtered, or relocated tag turns streaming off for every page that uses the layout. - Keep the layout head cheap in Liquid. Shopify renders everything above the tag before it can send the first part.
- Section Liquid still costs the same. Streaming moves the browser's fetches earlier, but the page can't paint content until the sections arrive, so the Liquid best practices still matter.
- On a streamed page, the TTFB a tool reports marks when the first part arrives, not when rendering finishes. Your server-side work still shows in the document request's total duration. See Measuring Liquid rendering time for how to read DevTools timings.
Anchor to MinificationMinification
Shopify automatically minifies CSS files, as well as JavaScript files that use valid syntax to ES5, when the storefront requests them. Minified JavaScript and CSS files are cached until the next time the file is updated.
Minification reduces the amount of data that the browser downloads, which results in shorter load times.
Shopify delivers the original version of a JavaScript or CSS file if it meets one of the following criteria:
- The minified file would be larger than the original file. This might happen if a file is already minified with better compression.
- It has the extension
.min.jsor.min.css.
Minification might remove debugger statements from code. To debug your code, you can temporarily change your file extension to .min.js or .min.css.
Minification might remove debugger statements from code. To debug your code, you can temporarily change your file extension to .min.js or .min.css.
Anchor to Early HintsEarly Hints
Shopify tells the browser about your render-blocking resources before it sends the HTML, using HTTP 103 Early Hints. The browser can open connections and start downloading those files while Shopify's servers are still rendering the page. This happens on every storefront and requires no changes to your theme.
On each storefront HTML response, Shopify scans the rendered <head> for the scripts and stylesheets that block rendering, then sends Link headers that preload those files and preconnect to the third-party origins that serve them. Shopify limits the number of entries so the header stays within the size that browsers support. Automatic hints are placed first, and the hints that your theme adds through preload_tag, stylesheet_tag: preload: true, and image_tag: preload: true fill the remaining space.
Shopify monitors storefront performance and adds resource hints automatically to mitigate platform-wide issues. These mitigations can change over time, so don't build your theme around them. Follow the best practices in this section instead, and treat the automatic hints as a safety net.
Anchor to What this means for your themeWhat this means for your theme
- You don't need to do anything. Shopify sends the hints for the render-blocking scripts and stylesheets in your
<head>for every storefront page, so don't add your own preload or preconnect hints for those files. - If a specific resource needs a hint, such as an LCP image the browser discovers late, add it with
preload_tagorimage_tag: preload: trueand keep it to one or two. Every hint, automatic or yours, takes a slot in the same limited header, so overdoing it pushes out the hints that matter. See Use preload resource hints sparingly. - Early Hints and streamed HTML responses stack. The hints start the downloads before the HTML arrives, and streaming lets the browser parse the top of your
<head>while your sections render. - Early Hints move resource discovery earlier. They don't make files smaller or the connection faster, so deferring non-critical resources and reducing stylesheet count still matter.
For guidance on the hints that remain in your hands, see Use preload resource hints sparingly and Warm up third-party connections early with preconnect. For the measured impact, read Faster Shopify storefronts with automatic Early Hints.
Anchor to Speculation rulesSpeculation rules
To improve buyer experience on Shopify stores, Shopify automatically injects speculation rules in supporting browsers.
The default rules aim to provide the largest speed gains without introducing issues with data usage, caching, or analytics. Themes can add extra rules of their own based on specific requirements and opportunities. See Use the Speculation Rules API for implementation guidance.
Anchor to PolyfillsPolyfills
Shopify automatically includes the es-module-shims polyfill library in the storefront when needed. This library enhances compatibility for modern JavaScript module features, primarily import maps, across different browsers.
Import maps are a standard web platform feature that you can use to control how JavaScript modules are resolved, similar to server-side package managers. Although they're widely supported in the latest versions of major browsers, older browser versions might lack native support for import maps or other newer module features that es-module-shims polyfills, such as multiple import maps in the same document.
In your theme code, you can use features like <script type="importmap"> tags and standard <script type="module"> tags without needing to manage browser-specific compatibility concerns for module loading yourself. Shopify makes sure this polyfill is included, and maintains it as long as necessary to support a reasonable range of browser versions used by buyers.
If possible, rely on this platform-provided polyfill for import map functionality. Avoid loading a separate version of es-module-shims or similar polyfills, because this could lead to conflicts or unnecessary overhead. See Use import maps for module resolution.
If possible, rely on this platform-provided polyfill for import map functionality. Avoid loading a separate version of es-module-shims or similar polyfills, because this could lead to conflicts or unnecessary overhead. See Use import maps for module resolution.
Anchor to Pagination limitsPagination limits
Shopify limits pagination of arrays of objects to 25,000 objects. Paginating deep into large arrays is resource-intensive and can slow down other requests. To keep all requests performant, a limit of 25,000 balances performance with practical use cases.
Pagination above 25,000 items suggests that you can find a more suitable design to help buyers narrow down their search to a manageable number of items before paging through all results. If you're constrained by this limit, then see how you can add filters to your store.
Shopify also enforces this limit on count queries. Counts are accurate up to 25,000 items. For arrays with more items, the count returns 25,001, which signals that there are more than 25,000 items in the array.
See Limit pagination depth for implementation guidance.