Shopify Functions vs Scripts: arhitectura WebAssembly explicată corect (cu limitele oficiale)
Ultima actualizare: 16 iunie 2026 | Surse: shopify.dev/docs — Functions↗, shopify.dev/docs/api/functions↗, shopify.engineering — WebAssembly↗, shopify.engineering — JavaScript in Wasm↗
Aproape fiecare blog tehnic despre Shopify Functions repetă aceleași cifre: „de 100 de ori mai rapide decât Scripts", „sub 5ms", „rulează în edge în milisecunde". Niciuna nu apare în documentația oficială curentă.
Acest teardown face ceea ce top-15 din SERP nu face: explică arhitectura reală citând direct sursele oficiale, tabelează limitele exacte și demontează miturile virale cu rigoare factuală.
TL;DR — diferența reală în 60 de secunde (compilat Wasm vs Ruby interpretat)
| Criteriu | Scripts (EOL 30 iun 2026) | Functions |
|---|---|---|
| Limbaj | Ruby interpretat | Orice limbaj → compilat la WebAssembly |
| Runtime | Sandbox izolat, acces complet cart | Infrastructura edge Shopify, input/output declarativ |
| Model date | Acces direct la obiecte Ruby | GraphQL input query → logică Wasm → JSON output |
| Determinism | Nu explicit | By design: fără random, fără clock, fără STDOUT |
| Limită runtime | Nedocumentată public | Instruction count (11M, dinamic) |
| Network access | N/A (sandbox Ruby) | Nuanțat: unele Functions au, cu restricții |
| Disponibilitate | Doar Shopify Plus | Orice plan (public apps) / Plus (custom apps) |
Dacă ai ajuns aici din ghidul de migrare Scripts → Functions, deja știi CE trebuie migrat. Acest articol explică DE CE funcționează noua arhitectură.
Arhitectura în 3 straturi:GraphQL input query → logică Wasm → output JSON declarativ
Modelul input → logică → output (run.graphql → run.rs/run.js → „operations")
Functions funcționează pe un model strict de trei pași:
- Input: Definești un GraphQL input query (
run.graphql) care selectează exact datele de care ai nevoie din contextul Shopify (coș, client, metafields). Shopify rulează acest query înainte de a apela Function-ul și pasează rezultatul JSON ca input. - Logică: Codul tău (Rust, JavaScript sau orice limbaj compilabil la Wasm) procesează input-ul JSON și produce output-ul.
- Output: Un document JSON cu o listă de „operații" declarative pe care Shopify le execută. Nu returnezi un cart modificat — returnezi instrucțiuni (ex: „aplică discount de 10% pe linia X").
Citat oficial: „Before calling your target, Shopify runs its associated GraphQL query and passes the resulting JSON data to your target."
Sursa: shopify.dev/docs/api/functions↗.
Function Targets injectează cod în backend logic-ul Shopify
Function-urile nu sunt endpoint-uri externe apelate prin HTTP. Sunt module Wasm care se injectează în backend logic-ul Shopify la puncte-țintă specifice (targets): discount, delivery customization, payment customization, cart transform, validare.
Citat oficial: „Function Targets inject code into the backend logic of Shopify."
Sursa: shopify.dev/docs — Functions↗.
WASM = compilat, nu interpretat (de ce contează față de Scripts)
Ruby dinamic nu compilează direct la Wasm — de ce Shopify a ales un limbaj static
Scripts foloseau Ruby — un limbaj dinamic interpretat. Ruby nu poate fi compilat direct la WebAssembly din cauza naturii sale dinamice (duck typing, eval, method_missing).
În implementarea timpurie, Shopify a ales AssemblyScript (un subset de TypeScript compilabil la Wasm) și apoi Rust. Citat oficial: „We decided to go with a statically compiled language and revisit the possibility of dynamic languages in the future."
Astăzi, JavaScript este suportat oficial prin pachetul @shopify/shopify_function (≥2.0.0), dar Shopify recomandă Rust (crate shopify_function ≥1.0.0) pentru performanță superioară: „Languages that compile directly to WebAssembly, such as Rust, perform better than dynamic languages, such as JavaScript."
Surse: shopify.engineering — WebAssembly↗ (18 decembrie 2020) · shopify.dev/docs — programming languages↗.
Argumentul de securitate:„you cannot express anything malicious in Wasm"
WebAssembly are un avantaj de securitate fundamental:
- „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."
Asta înseamnă: un Function nu poate accesa fișiere, rețea, memorie partajată sau orice resursă a host-ului fără ca Shopify să o permită explicit prin importuri. Sandbox-ul este arhitectural, nu doar prin convenție.
Sursa: shopify.engineering — WebAssembly↗ (18 decembrie 2020).
Determinism by design:fără random, fără clock, fără STDOUT/STDERR
Citat oficial: „Shopify doesn't allow nondeterminism in functions, which means that you can't use any randomizing or clock functionality in your functions."
De asemenea, nu poți face debug prin STDOUT sau STDERR — output-ul standard nu este capturat. Debug-ul se face prin logurile de eroare documentate (max 1 kB, trunchiate).
Asta e o restricție de design, nu un bug. Shopify vrea ca o Function să producă exact același output pentru același input, indiferent de momentul execuției. Determinismul garantează reproductibilitatea la scară.
Sursa: shopify.dev/docs/api/functions↗.
Fără apeluri externe live by default (network access nuanțat)
Anumite Functions au network access sub restricții; endpoint nesuportat ⇒ 502 Not supported
Mitul simplificat: „Functions nu au network access deloc." Realitatea e nuanțată:
Network access există pentru anumite Functions, sub restricții stricte. Nu orice Function poate face apeluri externe, și nu către orice endpoint.
Dacă apelezi un endpoint nesuportat, funcția rulează local dar nu se trimite niciun request real — target-ul primește un răspuns cu status „502 — Not supported".
Sursa: shopify.dev/docs — network access↗.
Output pur declarativ (operații), nu răspuns HTTP — nu manipulezi headere
Un Function nu returnează un răspuns HTTP. Returnează un document JSON cu o listă de operații declarative. Nu manipulezi request headers, nu setezi cookies, nu faci redirect-uri. Shopify procesează operațiile și le aplică în backend.
Asta e diferența fundamentală față de middleware-ul clasic sau serverless functions. Un Shopify Function nu e un endpoint — e o transformare de date.
Limitele oficiale exacte (tabel de citat în articol)
Limite fixe
| Resursă | Limită |
|---|---|
| Binar compilat Wasm | max 256 kB |
| Memorie liniară runtime | 10.000 kB |
| Memorie stack runtime | 512 kB |
| Loguri scrise | 1 kB (trunchiat) |
Limite dinamice (până la 200 line items)
| Resursă | Limită (≤200 line items) | Peste 200 |
|---|---|---|
| Instruction count | 11 milioane instrucțiuni | Scalează proporțional |
| Input funcție | 128 kB | Scalează proporțional |
| Output funcție | 20 kB | Scalează proporțional |
Limita de „instruction count" este cea mai importantă — și cea mai prost înțeleasă. Nu e o limită de timp. Este o limită de complexitate computațională a modulului Wasm.
Sursa: shopify.dev/docs/api/functions↗.
Demontarea miturilor virale (rigoarea care lipsește din top-15)
Runtime-ul se măsoară în INSTRUCTION COUNT (11M), NU în milisecunde
Erorile de runtime documentate oficial includ:
InstructionCountLimitExceededErrorStackMemoryLimitExceededErrorLinearMemoryLimitExceededErrorOutputTooLargeErrorInputSizeLimitExceededError
Observă: niciun ExecutionTimeLimitExceededError. Pagina oficială de limite nu publică niciun prag de timp de execuție în milisecunde.
Surse: shopify.dev/docs — monitoring and errors↗ · shopify.dev/docs/api/functions↗.
„5ms" e o cifră de blog din 2023, calificată de Shopify ca „machine-dependent and situational"
Cifra de 5ms provine dintr-un articol Shopify Engineering din februarie 2023 despre JavaScript în WebAssembly. Contextul exact: era o constrângere de dezvoltare internă, nu o limită de produs.
Citat oficial: „The module must not run longer than 5ms" — dar Shopify o califică explicit ca fiind „a very machine-dependent and situational constraint."
Nu apare în documentația curentă de produs. Nu e o limită oficială. Este o cifră de inginerie din 2023 care a fost preluată viral de bloguri fără context.
Sursa: shopify.engineering — JavaScript in WebAssembly for Shopify Functions↗ (9 februarie 2023).
„100x faster than Scripts" NU apare în nicio sursă oficială Shopify
Am verificat: shopify.dev, shopify.engineering, changelog.shopify.com, help.shopify.com. Niciun document oficial Shopify conține afirmația „100x faster" sau „de 100 de ori mai rapid".
Este o cifră de marketing apărută în bloguri terțe. Poate fi plausibilă ca ordin de mărime (Wasm compilat vs Ruby interpretat), dar nu este o afirmație oficială Shopify și nu trebuie citată ca atare.
Optimizări recente:Wasm query API (mai 2025) cu deserializare just-in-time
În mai 2025, Shopify a lansat Functions Wasm query API — o optimizare care permite deserializare just-in-time: Function-ul citește doar câmpurile efectiv folosite din input, eliminând overhead-ul de a include un parser JSON complet în binar.
Rezultat: funcții mai mici (sub limita de 256 kB) și mai eficiente (mai puține instrucțiuni consumate pe parsing).
Dacă ai Functions existente cu binar aproape de 256 kB, aceasta e o cale concretă de optimizare.
Sursa: shopify.dev/changelog — Functions Wasm query API↗ (21 mai 2025).
Rust vs JavaScript:când alegi care (onest, nu „Rust întotdeauna")
Shopify recomandă Rust. Dar recomandarea onestă e mai nuanțată:
Alege Rust când:
- Ai Function-uri complexe aproape de limita de 11M instrucțiuni
- Binarul trebuie să rămână sub 256 kB (Rust produce binare semnificativ mai mici)
- Echipa ta are experiență Rust sau e dispusă să investească în învățare
- Performanța e critică (volume mari de line items)
Alege JavaScript când:
- Ai developeri familiari cu JS/TS care trebuie să livreze rapid
- Logica de business e simplă (discount pe tag, filtru de plată, redenumire transport)
- Iterezi frecvent și vrei un ciclu de dezvoltare mai scurt
- Ești confortabil cu overhead-ul mai mare (binar mai mare, mai multe instrucțiuni)
Nu e o alegere absolută. E un trade-off între performanță și productivitate. Functions JS rulează în producție pe milioane de magazine Shopify.
Surse: shopify.dev/docs — programming languages↗.
Disponibilitate și context de migrare (orice plan vs Plus; Scripts sunset 30 iun 2026)
- Orice plan: poate folosi aplicații publice din App Store care conțin Functions.
- Doar Plus: poate rula custom apps cu Function APIs construite cu Shopify CLI.
- Batch limit: un singur Function API poate executa până la 25 de funcții într-un batch (crescut de la 5), pentru Payment/Delivery customizations, Cart/checkout validations și Fulfillment constraints.
Scripts (Script Editor) erau disponibile exclusiv pe Shopify Plus. Sunset-ul e pe 30 iunie 2026 — pașii practici de migrare sunt detaliați în ghidul nostru complet de migrare.
Surse: shopify.dev/docs/api/functions↗ · shopify.dev/changelog — 25 functions limit↗ (21 mai 2025).
Unghiul de performanță și sustenabilitate
Din perspectiva ingineriei de mediu pe care o practicăm la Verdant Mindset:
Functions (WebAssembly pe infra edge) vs Scripts (Ruby interpretat pe server) = mai puțin CPU per execuție. La scara checkout-urilor Shopify (milioane zilnic), asta contează.
Dar nu inventăm cifre de CO2 — nu avem surse oficiale pentru impactul exact. Ce știm:
- Cod compilat Wasm e deterministic mai eficient decât Ruby interpretat.
- Eliminarea app-urilor terțe cu funcționalitate similară (acum nativă) reduce payload-ul JS al storefront-ului.
- Dovada VM: TTFB de 0.21s pe Shopify (Fitness Library) prin eliminarea app-urilor redundante.
Pentru arhitectura completă SEO + performanță pe Shopify: ghidul nostru de arhitectură SEO Shopify.
FAQ.PROTOCOL
