Shopify Functions vs Scripts: The WebAssembly Architecture Explained Correctly (With Official Limits)
Last updated: June 16, 2026 | Sources: shopify.dev/docs — Functions↗, shopify.dev/docs/api/functions↗, shopify.engineering — WebAssembly↗, shopify.engineering — JavaScript in Wasm↗
Nearly every technical blog about Shopify Functions repeats the same numbers: "100x faster than Scripts", "under 5ms", "runs at the edge in milliseconds." None of these appear in current official documentation.
This teardown does what the SERP top-15 doesn't: explains the real architecture citing official sources directly, tabulates the exact limits, and debunks viral myths with factual rigor.
TL;DR — the real difference in 60 seconds (compiled Wasm vs interpreted Ruby)
| Criterion | Scripts (EOL June 30, 2026) | Functions |
|---|---|---|
| Language | Interpreted Ruby | Any language → compiled to WebAssembly |
| Runtime | Isolated sandbox, full cart access | Shopify edge infrastructure, declarative I/O |
| Data model | Direct access to Ruby objects | GraphQL input query → Wasm logic → JSON output |
| Determinism | Not explicit | By design: no random, no clock, no STDOUT |
| Runtime limit | Not publicly documented | Instruction count (11M, dynamic) |
| Network access | N/A (Ruby sandbox) | Nuanced: some Functions have it, with restrictions |
| Availability | Shopify Plus only | Any plan (public apps) / Plus (custom apps) |
If you arrived here from our Scripts → Functions migration guide, you already know WHAT needs migrating. This article explains WHY the new architecture works.
The 3-layer architecture:GraphQL input query → Wasm logic → declarative JSON output
The input → logic → output model (run.graphql → run.rs/run.js → "operations")
Functions operate on a strict three-step model:
- Input: You define a GraphQL input query (
run.graphql) that selects exactly the data you need from the Shopify context (cart, customer, metafields). Shopify runs this query before calling your Function and passes the resulting JSON as input. - Logic: Your code (Rust, JavaScript, or any Wasm-compilable language) processes the JSON input and produces output.
- Output: A JSON document with a list of declarative "operations" that Shopify executes. You don't return a modified cart — you return instructions (e.g., "apply 10% discount on line X").
Official quote: "Before calling your target, Shopify runs its associated GraphQL query and passes the resulting JSON data to your target."
Source: shopify.dev/docs/api/functions↗.
Function Targets inject code into Shopify's backend logic
Functions are not external endpoints called via HTTP. They are Wasm modules that inject into Shopify's backend logic at specific target points: discount, delivery customization, payment customization, cart transform, validation.
Official quote: "Function Targets inject code into the backend logic of Shopify."
Source: shopify.dev/docs — Functions↗.
WASM = compiled, not interpreted (why it matters compared to Scripts)
Dynamic Ruby doesn't compile directly to Wasm — why Shopify chose a static language
Scripts used Ruby — an interpreted dynamic language. Ruby cannot be compiled directly to WebAssembly due to its dynamic nature (duck typing, eval, method_missing).
In the early implementation, Shopify chose AssemblyScript (a TypeScript subset compilable to Wasm) and then Rust. Official quote: "We decided to go with a statically compiled language and revisit the possibility of dynamic languages in the future."
Today, JavaScript is officially supported through the @shopify/shopify_function package (≥2.0.0), but Shopify recommends Rust (shopify_function crate ≥1.0.0) for superior performance: "Languages that compile directly to WebAssembly, such as Rust, perform better than dynamic languages, such as JavaScript."
Sources: shopify.engineering — WebAssembly↗ (December 18, 2020) · shopify.dev/docs — programming languages↗.
The security argument:"you cannot express anything malicious in Wasm"
WebAssembly has a fundamental security advantage:
- "You cannot express anything malicious in Wasm. You can only express manipulations of the virtual environment and use provided imports."
- "Wasm executes within a sandboxed stack-based environment, relying upon explicit imports to allow communication with the host."
This means: a Function cannot access files, network, shared memory, or any host resource without Shopify explicitly permitting it through imports. The sandbox is architectural, not just by convention.
Source: shopify.engineering — WebAssembly↗ (December 18, 2020).
Determinism by design:no random, no clock, no STDOUT/STDERR
Official quote: "Shopify doesn't allow nondeterminism in functions, which means that you can't use any randomizing or clock functionality in your functions."
Additionally, you cannot debug via STDOUT or STDERR — standard output is not captured. Debugging is done through documented error logs (max 1 kB, truncated).
This is a design restriction, not a bug. Shopify wants a Function to produce exactly the same output for the same input, regardless of execution time. Determinism guarantees reproducibility at scale.
Source: shopify.dev/docs/api/functions↗.
No live external calls by default (nuanced network access)
Some Functions have network access under restrictions; unsupported endpoint ⇒ 502 Not supported
The simplified myth: "Functions have no network access at all." The reality is nuanced:
Network access exists for certain Functions, under strict restrictions. Not every Function can make external calls, and not to any endpoint.
If you call an unsupported endpoint, the function runs locally but no actual request is sent — the target receives a response with status "502 — Not supported."
Source: shopify.dev/docs — network access↗.
Purely declarative output (operations), not an HTTP response — no header manipulation
A Function does not return an HTTP response. It returns a JSON document with a list of declarative operations. You don't manipulate request headers, set cookies, or perform redirects. Shopify processes the operations and applies them in the backend.
This is the fundamental difference from classic middleware or serverless functions. A Shopify Function is not an endpoint — it's a data transformation.
Exact official limits (table for citation)
Fixed limits
| Resource | Limit |
|---|---|
| Compiled Wasm binary | max 256 kB |
| Linear runtime memory | 10,000 kB |
| Stack runtime memory | 512 kB |
| Written logs | 1 kB (truncated) |
Dynamic limits (up to 200 line items)
| Resource | Limit (≤200 line items) | Above 200 |
|---|---|---|
| Instruction count | 11 million instructions | Scales proportionally |
| Function input | 128 kB | Scales proportionally |
| Function output | 20 kB | Scales proportionally |
The instruction count limit is the most important — and the most poorly understood. It's not a time limit. It's a computational complexity limit for the Wasm module.
Source: shopify.dev/docs/api/functions↗.
Debunking viral myths (the rigor missing from the top-15)
Runtime is measured in INSTRUCTION COUNT (11M), NOT in milliseconds
Officially documented runtime errors include:
InstructionCountLimitExceededErrorStackMemoryLimitExceededErrorLinearMemoryLimitExceededErrorOutputTooLargeErrorInputSizeLimitExceededError
Notice: no ExecutionTimeLimitExceededError. The official limits page publishes no execution time threshold in milliseconds.
Sources: shopify.dev/docs — monitoring and errors↗ · shopify.dev/docs/api/functions↗.
"5ms" is a 2023 blog figure, qualified by Shopify as "machine-dependent and situational"
The 5ms figure comes from a Shopify Engineering article from February 2023 about JavaScript in WebAssembly. The exact context: it was an internal development constraint, not a product limit.
Official quote: "The module must not run longer than 5ms" — but Shopify explicitly qualifies this as "a very machine-dependent and situational constraint."
It does not appear in current product documentation. It is not an official limit. It's a 2023 engineering figure that was virally adopted by blogs without context.
Source: shopify.engineering — JavaScript in WebAssembly for Shopify Functions↗ (February 9, 2023).
"100x faster than Scripts" does NOT appear in any official Shopify source
We checked: shopify.dev, shopify.engineering, changelog.shopify.com, help.shopify.com. No official Shopify document contains the claim "100x faster" or any variation of it.
It's a marketing figure from third-party blogs. It may be plausible as an order of magnitude (compiled Wasm vs interpreted Ruby), but it is not an official Shopify claim and should not be cited as such.
Recent optimizations:Wasm query API (May 2025) with just-in-time deserialization
In May 2025, Shopify launched the Functions Wasm query API — an optimization enabling just-in-time deserialization: the Function reads only the fields actually used from the input, eliminating the overhead of including a full JSON parser in the binary.
Result: smaller functions (staying under the 256 kB limit) and more efficient execution (fewer instructions consumed on parsing).
If you have existing Functions with binaries approaching 256 kB, this is a concrete optimization path.
Source: shopify.dev/changelog — Functions Wasm query API↗ (May 21, 2025).
Rust vs JavaScript:when to choose which (honestly, not "Rust always")
Shopify recommends Rust. But the honest recommendation is more nuanced:
Choose Rust when:
- Your Functions are complex, approaching the 11M instruction limit
- The binary must stay under 256 kB (Rust produces significantly smaller binaries)
- Your team has Rust experience or is willing to invest in learning
- Performance is critical (high line-item volumes)
Choose JavaScript when:
- You have JS/TS developers who need to ship quickly
- Business logic is simple (discount on tag, payment filter, shipping rename)
- You iterate frequently and want a shorter development cycle
- You're comfortable with the higher overhead (larger binary, more instructions)
It's not an absolute choice. It's a trade-off between performance and productivity. JS Functions run in production on millions of Shopify stores.
Source: shopify.dev/docs — programming languages↗.
Availability and migration context (any plan vs Plus; Scripts sunset June 30, 2026)
- Any plan: can use public apps from the App Store that contain Functions.
- Plus only: can run custom apps with Function APIs built with Shopify CLI.
- Batch limit: a single Function API can execute up to 25 functions in a batch (increased from 5), for Payment/Delivery customizations, Cart/checkout validations, and Fulfillment constraints.
Scripts (Script Editor) were available exclusively on Shopify Plus. Sunset is June 30, 2026 — practical migration steps are detailed in our complete migration guide.
Sources: shopify.dev/docs/api/functions↗ · shopify.dev/changelog — 25 functions limit↗ (May 21, 2025).
The performance and sustainability angle
From the environmental engineering perspective we practice at Verdant Mindset:
Functions (WebAssembly on edge infra) vs Scripts (interpreted Ruby on server) = less CPU per execution. At the scale of Shopify checkouts (millions daily), this matters.
But we don't fabricate CO2 figures — we don't have official sources for the exact impact. What we know:
- Compiled Wasm code is deterministically more efficient than interpreted Ruby.
- Eliminating third-party apps with now-native functionality reduces storefront JS payload.
- VM proof: TTFB of 0.21s on Shopify (Fitness Library) through eliminating redundant apps.
For the complete SEO + performance architecture on Shopify: our Shopify SEO architecture guide.
FAQ.PROTOCOL
