Shopify’s Staff Engineer Guilherme Carreiro breaks down how the Liquid theme system balances extreme design flexibility with sub‑second latency at millions of requests per minute, covering DSL design, safe extensibility, native‑extension performance tricks, and the tooling that keeps theme developers productive.
Theme Systems at Scale – What Shopify’s Liquid Teaches Us

Shopify stores look wildly different, yet the underlying rendering pipeline serves up to 6 million requests per minute during Black Friday‑Cyber Monday. The secret lies in a carefully engineered theme system that lets designers, merchants, and app developers collaborate without sacrificing performance.
1. Why a New Template Language Was Needed
When Shopify started, its front‑end was built with Ruby’s ERB templates. ERB gives you full Ruby power, which is great for internal code but disastrous for a platform that accepts third‑party templates. A malicious or naïve template could trigger N+1 database queries, execute arbitrary Ruby, or simply stall the request pipeline.
Liquid was created as a whitelisted DSL:
- only a fixed set of tags (
if,for,assign,capture, …) - no direct database access – data is exposed through drops (lightweight, memoised objects that expose a curated API)
- built‑in resource limits (render length, variable count) to stop runaway templates
These constraints give the platform a predictable execution envelope while still letting developers place a product price, a loop of products, or a custom filter anywhere on the page.
2. Making the DSL Friendly for Non‑Technical Merchants
A theme is more than a collection of HTML files; it is a package that contains:
- Liquid templates – the markup that renders data
- JSON schema files – a description of configurable settings for each component
The JSON schema is the bridge between developers and merchants. By declaring a property like image_position with allowed values left | right, the visual editor can render a dropdown for the merchant. The merchant never touches Liquid code; they simply pick a value, and the editor writes the JSON, which the Liquid template reads at render time.
This pattern of sections → blocks → schema creates a shared vocabulary that both technical and non‑technical personas understand, enabling rapid iteration without breaking the underlying rendering contract.
3. Keeping the Rendering Pipeline Fast at Scale
3.1 Multi‑tenant Architecture & Data Replication
Shopify runs on Google Cloud with a sharded, multi‑tenant model. Each shop’s data lives in its own database instance, keyed by the shop ID. Writes go to the primary shard synchronously; reads for storefront traffic hit asynchronously replicated replicas that are tuned for low‑latency access.
3.2 Native Extensions for Hot Paths
Most of Shopify’s codebase is Ruby, but the Liquid renderer has a few hot paths that would suffer from Ruby’s garbage‑collector pauses. The solution is a Rust native extension that:
- parses Liquid ASTs into an efficient in‑memory representation
- performs JSON decoding for schema files
- executes the filter pipeline (price formatting, currency conversion, etc.)
Because the extension lives in the same process, the call overhead is tiny, but developers must be careful to avoid memory leaks – the extension manages its own heap.
3.3 Bench‑mark‑Driven Extraction
Not every piece of code deserves a native extension. The rule of thumb is:
- Identify a function that runs many times per request (e.g., a filter applied to every line‑item).
- Measure the Ruby implementation vs. a pure‑Rust version.
- If the Rust version is at least 2× faster and the call frequency is high enough to amortise the serialization cost, promote it.
4. Tooling – Turning a DSL into a Developer‑Friendly Platform
4.1 Profiler (shopify theme profile)
Running the profiler locally shows per‑section render times, helping developers shrink Time‑to‑First‑Byte. The data is also used in CI to enforce a maximum TTFB budget for published themes.
4.2 Linter (theme check)
The linter catches common mistakes:
- usage of deprecated drops
- missing schema properties
- potential N+1 loops (detected by static analysis of nested
fortags)
When a problem is found, the IDE highlights it with a quick‑fix suggestion.
4.3 Language Server (VS Code)
A custom language server provides:
- autocomplete for drops and filters
- hover documentation generated from the schema JSON
- tolerant parsing that keeps the IDE functional even with unfinished templates
The server re‑uses Microsoft’s JSON language server for the schema files, meaning the team only had to implement the Liquid‑specific layer.
4.4 Parser Choices
Shopify maintains two parsers:
- Fast renderer parser – minimal, strict, optimized for production
- Tooling parser – tolerant, built with the Ohm library, capable of recovering from syntax errors and providing rich diagnostics for the IDE
5. Designing Your Own Theme System
If you are building a theme platform from scratch, consider these four pillars:
- A safe, expressive DSL – start with an allow‑list model; expose data through drops or similar wrappers.
- Schema‑driven extensibility – let non‑technical users edit JSON that feeds directly into your templates.
- Performance‑first runtime – evaluate native extensions early; keep the hot path in a compiled language.
- Developer tooling – a profiler, linter, and language server turn a good DSL into a great ecosystem.
When possible, adopt an existing language (Liquid, Handlebars, Mustache) to avoid reinventing the wheel. If you must create a new DSL, “Crafting Interpreters” by Bob Nystrom is an excellent hands‑on guide.
6. What This Means for Users
- Merchants gain a visual editor that updates JSON schemas, letting them reposition images, change colors, or add third‑party app blocks without touching code.
- Theme developers receive fast feedback on render performance and static‑analysis warnings, enabling them to ship high‑quality themes that survive traffic spikes.
- App developers can ship reusable Liquid snippets (e.g., reviews, discounts) that appear as selectable components in the merchant editor.
The result is a platform where design freedom and operational stability coexist, even under the pressure of millions of requests per minute.
7. Further Reading
- Official Liquid documentation – https://shopify.dev/docs/api/liquid
- Shopify’s open‑source theme‑check repo – https://github.com/Shopify/theme-check
- The Rust‑based Liquid renderer – https://github.com/Shopify/liquid-rust
- “Crafting Interpreters” – https://craftinginterpreters.com
The insights above are drawn from Guilherme Carreiro’s talk at the InfoQ Dev Summit Munich (June 2026).

Comments
Please log in or register to join the discussion