Shopify Discount Functions Explained (2026 Guide)

Shopify discount functions replaced Scripts as the only way to build custom discount logic on Shopify. Here's how they work, what changed, and what breaks when a membership discount meets a promo code.

A merchant messaged us in June with a simple question: why did a customer's VIP discount and a site-wide promo code both apply to the same product, stacking into a price that lost money on the order. The answer had nothing to do with a bug. It had to do with how Shopify discount functions decide which discount wins when two of them want the same line item, and almost nobody reads that part of the documentation until it costs them money.

Shopify discount functions are server-side WebAssembly modules that calculate and apply discounts during cart and checkout, replacing the Ruby-based Shopify Scripts that shut down for good on June 30, 2026. A function receives cart data as structured input, runs custom logic against it, and returns a list of operations Shopify executes at checkout: apply 10% off this line, discount the whole order by $25, knock 50% off Express Shipping. The function itself lives inside an app. Merchants never touch code; they see a new discount type in the same Discounts page they've always used.

That distinction matters more than it sounds. Scripts ran inline in the Shopify admin's Script Editor, wrote in Ruby, and only worked on Shopify Plus. Discount functions are compiled ahead of time, distributed through an app, and available to every plan (Basic, Shopify, Advanced, and Plus) the moment a merchant installs an app that contains one. A custom, private function still requires Plus, but a public app built on the Discount Function API works everywhere.

What Do Shopify Discount Functions Actually Do?

A discount function is a small program that decides, in under 5 milliseconds, whether a discount applies to a cart and how much it's worth. Shopify's own developer docs put a hard number on that speed target, and it's not marketing. Functions run inside the checkout request itself, so a slow function means a slow checkout. There are three discount classes a single function can touch: product, order, and shipping. One function can reduce a product's price, knock a flat amount off the order subtotal, and discount the delivery fee all in the same execution.

Under the hood, a function is built with the Shopify CLI, written in Rust or JavaScript, and compiled to WebAssembly before it ever reaches a live store. It reads a GraphQL input (cart lines, customer tags, quantities, metafields) and returns a FunctionRunResult telling Shopify exactly which lines to discount and by how much. Nothing about that logic is visible to the shopper beyond the discount message they see at checkout, like "Member price applied."

How Are Shopify Functions Different From Shopify Scripts?

Scripts gave a single Ruby program full control over the entire cart in one pass; functions run as isolated, independent modules that never see each other. That's the single biggest behavior change merchants hit during migration, and it's the reason the VIP-discount-plus-promo-code scenario above turned into a support ticket.

With Scripts, a developer could write one program that checked ten conditions in sequence and applied a loyalty discount, a promo code, and a shipping override all in one coherent block of logic. With functions, each discount is its own separate extension. Shopify can run up to 25 discount functions on a single store at once, and none of them know the others exist. What decides the outcome is the combination strategy configured on each discount: FIRST lets the earliest-created discount win, MAXIMUM picks whichever discount is worth more, and for order- and shipping-level discounts, ALL lets every eligible discount stack. Product-level discounts don't currently support ALL. Only one product discount can land on a given line item, no matter how many are eligible.



Shopify Scripts

Shopify Functions

Language

Ruby

Rust or JavaScript, compiled to WebAssembly

Where it lives

Script Editor, Shopify admin

Distributed as an app

Plan availability

Shopify Plus only

All plans, via public apps

Multiple discounts

One script sees the whole cart

Isolated functions, combined via strategy rules

Status

Deprecated, stopped executing June 30, 2026

Current standard

Why Discount Stacking Behaves Differently Now

A store credit or membership discount that used to stack cleanly with a promo code under Scripts can now lose to it, cancel it out, or apply on top of it depending entirely on how the discount node is configured. This is the part of the migration nobody wrote about at length, and it's exactly where retention programs get exposed.

Think about a typical VIP setup: a member gets an automatic 15% discount on every order, funded by their subscription. A marketing team runs a 20% off sitewide promo for a flash sale. Under the old Scripts model, a developer decided explicitly how those two combined, usually the better one won, applied cleanly, end of story. Under functions, if both discounts are configured as product discounts with a FIRST strategy, whichever one was created first in the admin wins outright, even if it's worth less to the customer. Get the combination settings wrong and a VIP member either double-dips into a stack that erodes margin, or gets locked out of a promo they should have qualified for.

Store credit sits outside this problem entirely, which is worth calling out because it's a common point of confusion. Store credit isn't a discount function at all. It's applied as a payment method at the order level, after every discount has already been calculated. That's a structural difference worth understanding before assuming a credit-based membership program needs to fight for position in the discount stack the way a percentage-off VIP discount does.

Where Merchants Get This Wrong

The most common mistake is treating discount functions like Scripts with new syntax, when the actual mental model is closer to running several independent programs that each need to be told explicitly how to coexist. A few patterns show up repeatedly:

  1. Configuring a loyalty or membership discount and a promotional discount as separate product-level functions, then being surprised when only one applies to a shared line item.

  2. Building a function that queries large product collections on every run, which can time out or fail outright on collections with thousands of products. Functions have fixed resource limits, and a poorly scoped query burns through them fast.

  3. Writing functions in JavaScript for a store with big carts, when Shopify's own guidance is that Rust handles large cart volume more reliably because of its lower memory overhead.

  4. Assuming the migration is a code-only project and skipping the business decision of which discount should actually win when two now-isolated functions both want the same customer.

Do You Need a Developer to Build a Discount Function?

Not for standard use cases. Tiered pricing, BOGO, free-gift-with-purchase, and shipping promos are all available through App Store apps already built on the Discount Function API, with no code required. Custom stacking logic tied to a specific membership model, or rules no app already covers, is where a private function and a developer earn their keep. For a Shopify Plus store running something as specific as store-credit-funded membership pricing sitting alongside promotional discounts, that's usually not a five-minute app install. It's a deliberate decision about combination strategy, tested against real carts before it goes live.

That's the exact problem retention platforms exist to solve for merchants who don't want to own a WebAssembly build pipeline just to keep a loyalty program running correctly. Subscribfy's membership product runs on Shopify's native checkout rather than script injection, which means the store-credit and VIP-pricing layer was never exposed to the Scripts shutdown in the first place. It was built for the functions-era architecture from day one. Brands running chargeback prevention alongside a membership program hit a similar version of this question: which system gets to make the final call at checkout, and does it actually get tested against edge cases before a sale goes live.

FAQ

What is the difference between a discount code and a discount function?

A discount code is what a customer types in; a discount function is the logic that decides what happens once a discount, code-based or automatic, is triggered. A single function can power either kind.

Can I still use Shopify Scripts in 2026?

No. Shopify Scripts stopped executing entirely on June 30, 2026, and merchants who hadn't migrated by then lost that checkout logic without warning.

Do non-Plus stores get access to discount functions?

Yes. Any store on any plan can install a public app from the Shopify App Store that contains a discount function. Custom, privately built functions still require Shopify Plus.

How many discount functions can run on one store?

Up to 25 discount functions can be active on a single store, all running concurrently and independently of each other.

Why did my VIP discount stop stacking with a promo code after migrating from Scripts?

Because discount functions don't share awareness of each other the way a single Script did. The combination strategy set on each discount (FIRST, MAXIMUM, or ALL) now decides the outcome, and it needs to be configured deliberately rather than assumed.

Image

Book a meeting with our sales team now!

Create predictable revenue from the customers you already have.