Backend logic

Shopify Functions Development

Shopify Functions let you replace parts of Shopify's own backend logic — how a cart is priced, discounted, bundled, delivered and paid for. Written in Rust or JavaScript, compiled to WebAssembly, and executed on Shopify's infrastructure rather than a server you have to keep alive.

Book a Free Technical Call
Shopify Functions written in Rust and compiled to WebAssembly for cart transform and discount logic

Why it matters

Functions are how Shopify lets you change what it does, not just what it looks like.

Shopify Scripts have been retired, and Functions are the supported replacement — but they're also a genuine upgrade. A Function runs inside Shopify's checkout on Shopify's own infrastructure, so there's no server of yours to scale, no latency you own, and no third-party endpoint that can take checkout down at 9pm on Black Friday. The trade-off is discipline. Functions run inside a hard instruction budget, roughly five milliseconds of work, and they cannot make network calls at all. Every input has to already exist in Shopify. That constraint is the whole design problem, and it's where most of the value of hiring someone senior actually sits.

Sound familiar?

Functions usually come up after something else stopped working.

Most of these are solid reasons to write a Function. One of them is a misunderstanding of what a Function can reach, and it's the single most common one we hear.

  • Your tiered or trade pricing lives in a spreadsheet, and staff apply it manually at checkout.
  • Your bundle app rewrites the cart, and inventory or reporting disagrees with what actually sold.
  • You show express shipping to postcodes that can't receive it, and support handles the fallout.
  • You assume a Function can call your ERP mid-checkout to price an order in real time.
  • Your Scripts stopped working and the app you replaced them with covers half the rules.
  • You hide payment methods with checkout JavaScript that breaks whenever Shopify ships a change.

What's included

What we build with Functions

Commerce rules expressed as code that runs where the platform runs — versioned, tested and configurable without a deploy.

Discount Functions

Product, order and shipping discounts written as code rather than stacked across three promotion apps. Volume breaks, trade tiers, buy-X-get-Y with exclusions, member-only pricing. Because the logic runs server-side, the same rule holds in the cart, at checkout and through the Storefront API — no client-side patching to keep in sync.

Cart transform

Merging separate lines into a single bundle, expanding a bundle into its components so the right SKUs are decremented, or changing how a line is presented and priced. This is what makes bundles behave correctly for inventory, fulfilment and reporting instead of being a cosmetic trick. The Cart Transform API requires Shopify Plus.

Delivery customisation

Rename, reorder or hide delivery options based on what's actually in the cart — hide express for oversized items, hide standard for perishables, rename a method into language a customer understands. Far more reliable than the checkout script hacks it replaces, and it survives Shopify's updates. Plus-gated.

Payment customisation and validation

Hide cash on delivery above a threshold, reorder wallets per market, or block a checkout that breaks a real business rule — minimum order value, restricted product and postcode combinations, trade-only lines. Both APIs are Plus-gated, and validation messages need wording a customer can actually act on.

Built for the execution limits

Functions run inside a fixed instruction budget — on the order of five milliseconds — with no network access whatsoever. Every input comes from a GraphQL input query you define against data already in Shopify. We design the data model around that first, because a Function that blows its budget simply doesn't apply and the customer sees the wrong price.

Rust or JavaScript, deployed properly

Rust where the instruction budget is tight or the cart can get very large; TypeScript compiled through Javy where the logic is simple and your team needs to read it. Either way it's version-controlled, unit-tested against real cart fixtures, and shipped through the Shopify CLI inside your app.

How it runs

How a Functions engagement actually runs.

Usually 3–6 weeks for a single Function, longer when several interact or discount combination rules get involved. Most of that time goes into writing the rules down precisely — the Rust is the short part.

  1. 01

    Write the rules down

    Every edge case, in a document you sign off: what stacks with what, what happens at zero or at a negative margin, which customers are excluded. Ambiguity here becomes a support ticket later, so we argue about it now.

  2. 02

    Model the inputs

    Functions can't call anything, so the data has to already be in Shopify. We map each rule onto metafields, metaobjects, customer segments or tags, then design the input query to fetch only what the logic genuinely needs.

  3. 03

    Build and benchmark

    Written, unit-tested against real cart fixtures, then run against your largest realistic basket to measure instruction usage. A rule that works on a three-line cart and fails on a forty-line one is a broken rule.

  4. 04

    Ship configurable

    Thresholds and values live in metafields so your team can change numbers without a code release. Deployed through the CLI, activated on one discount or customisation first, then widened once the orders look right.

WebAssembly

Runs on Shopify

No server of yours

~5ms

Execution budget

Instruction-capped per run

Rust / JS

Toolchain

Compiled via Shopify CLI

Plus

Gated APIs

Cart, delivery, payment

Straight answer

Functions are the right tool for a narrow, specific kind of problem.

A good fit if…

  • You have pricing or discount rules no app expresses properly, and you can write them down precisely.
  • You're on Shopify Plus and need cart transform, delivery or payment customisation behaviour.
  • You had Scripts doing real commercial work and need equivalent logic on a supported platform.
  • Your rules depend on data you can hold in metafields or metaobjects, not a live external lookup.

Probably not, if…

  • Your logic needs a live call to an external pricing service — Functions cannot make network requests.
  • You're not on Plus and need cart transform, delivery or payment customisation; those APIs are Plus-only.
  • An existing app already does exactly this well — custom code adds maintenance for no real gain.
  • Your rules change shape weekly and nobody on your side can deploy; new logic means a code release.

Frequently asked questions

  • Yes. Scripts have been retired and Functions are the supported path forward. They aren't a like-for-like port, though — Scripts ran Ruby with a different model of the cart, so logic has to be re-specified rather than translated line by line. In practice that's healthy: most Scripts we're handed have accumulated rules nobody can explain, and rewriting forces a decision about which ones still matter.

Got a pricing rule nothing can express?

Book a 30-minute technical call. Bring the rules, however messy. We'll tell you whether it needs a Function, an app, or nothing at all.

Book a free call