Performance best practices for Hydrogen storefronts
Most of this section assumes a Liquid theme, where Shopify renders and caches HTML for you and your work is mostly about what the browser does after the HTML arrives. Hydrogen is a React application that you write, build, and run yourself on Oxygen, so you own layers that the platform handles for a Liquid theme: data fetching, response caching, and how much JavaScript ships per route.
This page is the bridge. It maps Liquid theme performance concerns onto their Hydrogen equivalents, then points you at the dedicated Hydrogen performance guides for the implementation details.
Anchor to Set up analytics firstSet up analytics first
Configure analytics event tracking with Hydrogen before you optimize anything else. A Liquid theme reports Core Web Vitals to your Shopify Web Performance Dashboard without any setup. A Hydrogen storefront doesn't, so until tracking is wired up you have no field data, no regression detection, and no benchmark to compare against.
Anchor to Hydrogen and Liquid: where performance patterns divergeHydrogen and Liquid: where performance patterns diverge
| Concern | Liquid theme | Hydrogen storefront |
|---|---|---|
| Server render time | You optimize Liquid rendering: move work out of loops, avoid nested renders. Shopify runs the queries. | You write the queries. How you fetch data in route loaders dominates TTFB, so parallelize with Promise.all and don't over-fetch. See Performant data loading with Hydrogen. |
| Diagnosing a slow server response | Theme Inspector Chrome extension shows Liquid render time per section. | The Subrequest Profiler shows every request a route makes, in order, so you can spot waterfalls. |
| Response caching | Shopify's CDN caches storefront HTML. There's nothing to configure. | Subrequest caching is yours to choose per query (CacheShort, CacheLong, CacheNone), and full-page caching is opt-in through the Oxygen-Cache-Control header. See Caching and Oxygen full-page cache. |
| Partial page updates | Section Rendering API returns rendered section HTML. | Route loaders return data, and non-critical data streams in behind Suspense and Await instead of blocking the response. See Prioritize critical data. |
| JavaScript weight | Scripts are what you add to the theme, so you defer them or load them on interaction. | Every dependency a component imports lands in that route's bundle, whether or not the customer interacts with it. Import cost is the lever, so inspect your bundle size to find the heaviest dependencies. |
| Time to interactive | Server-rendered HTML is interactive as soon as your own scripts run. | React hydrates the server-rendered HTML before the page responds to input, so a heavy route can paint quickly and still feel unresponsive. This is an INP problem, not an LCP problem. |
| Startup cost | Not applicable. | Your worker has to boot on Oxygen. Measure it with npx shopify hydrogen debug cpu. See Measure CPU startup time locally. |
| Images | Liquid image filters plus explicit width and height. See Use responsive images. | Hydrogen's Image component generates srcset and sizes, and takes an aspectRatio prop to hold layout. See Render responsive images. |
| Speculative navigation | Speculation Rules API in the theme. | Built-in link pre-fetching with prefetch="intent" or prefetch="viewport". See Use pre-fetching. |
| Perceived latency on cart actions | Cart updates round-trip to the server. | useOptimisticCart and useOptimisticVariant update the UI before the server responds. See Implement optimistic UIs. |
Anchor to What carries over unchangedWhat carries over unchanged
These are browser-level constraints, so the guidance in this section applies to a Hydrogen storefront as written:
- Never lazy load the LCP image and set
fetchpriority="high"on it. - Prevent image layout shift by reserving dimensions.
- Font strategy: self-host web fonts and reduce CLS from font swapping.
- Render essential content server-side rather than fetching it from the client after load.
- Don't hide the LCP image behind animations, and use
transformfor animations.
Third-party scripts are the one case that looks the same and isn't. The main-thread cost is identical, but the delivery mechanism differs: in a Liquid theme a script is a tag you can defer or drop, whereas in Hydrogen a third-party SDK imported by a component becomes part of that route's JavaScript bundle. Auditing a Hydrogen storefront means reading the bundle size report as well as the network waterfall. The decision framework in Audit and remove third-party scripts still holds.
Anchor to TestingTesting
Hydrogen-specific tools:
- Subrequest Profiler for request waterfalls in loaders.
- Bundle size analyzer, through
npx shopify hydrogen buildoutput and the report it generates, for per-dependency JavaScript weight. npx shopify hydrogen debug cpufor worker startup time.
Browser tools, which work the same way as they do for a Liquid theme:
- Record a page load in the Chrome DevTools Performance panel, and look at the work after first paint to see how long hydration takes.
- Use the Coverage tab, under Sources, to find JavaScript that a route ships but doesn't run.
- Use the Lighthouse panel for lab LCP, CLS, and Total Blocking Time, which correlates with INP.
For field data, check your Shopify Web Performance Dashboard after analytics tracking is configured. See Testing for performance.
Anchor to ReferencesReferences
- Performant data loading with Hydrogen
- On-page optimizations
- Hydrogen debugging
- Caching in Hydrogen
- Analytics event tracking with Hydrogen
- Hydrogen production checklist