Move repeated assign and filter calls outside loops
Move calculations and filter operations outside of loops. Assign the result to a variable before the loop and reuse it, rather than recalculating on each iteration.
When you perform an operation inside a for loop that doesn't depend on the loop variable, you're calculating the same thing multiple times. The result doesn't change between iterations, but Liquid executes the operation again each time. Moving these operations before the loop reduces server-side Liquid execution time.
The impact scales with both the number of iterations and the cost of the operation. A sort filter inside a 50-product loop runs 50 times, producing the same sorted array each time. An asset_url filter that resolves the same asset path on every iteration wastes time resolving a value that could be resolved once. These add directly to TTFB, which delays FCP and LCP.
Identify any operation inside a loop whose result doesn't depend on the current iteration's variable. Move it above the loop and assign it to a variable.
Common operations to hoist:
assignwith static values: Anyassignthat doesn't reference the loop variable.captureblocks: Blocks that produce the same output on every iteration.image_url: When the image doesn't change per iteration, for example, a placeholder or brand logo.asset_url: Asset paths are the same on every iteration. Resolve them once.sortandwherefilters: Sorting or filtering a collection produces the same result each time.moneyfilter on static values: Formatting a fixed price or threshold.size: Counting the size of an array that doesn't change inside the loop.
Anchor to ExamplesExamples
Anchor to Basic: sort operation inside a loopBasic: sort operation inside a loop
Anchor to Real-world product card snippet with multiple hoistable operationsReal-world product card snippet with multiple hoistable operations
This example shows a product card loop where several operations are repeated on every iteration but produce the same result:
Less performant:
More performant:
In this example, four operations moved outside the loop. With 50 products, that's 200 fewer filter evaluations (4 operations × 50 iterations).
Anchor to Hoisting capture blocksHoisting capture blocks
Anchor to TestingTesting
- Use the Theme Inspector Chrome extension to identify repeated operations inside loops. The flame graph shows per-snippet timing, and the sandwich view shows cumulative time spent on repeated operations.
- Compare TTFB in the Chrome DevTools Network panel before and after hoisting operations. Filter to the document request and check the Waiting for server response time.
- Focus on collection pages and other pages where loops iterate many times. The impact scales with the iteration count.
Anchor to ReferencesReferences
fortagassigntagcapturetagasset_urlfilterimage_urlfiltermoneyfiltercollection.products- Debugging common causes for slow loading in Shopify Liquid storefronts
- Avoid deeply nested Liquid loops
- Avoid excessive conditionals in loops
- Avoid repetitive filter calls