Skip to content
HEAPBYTE

Engineering · April 2, 2026

When a Shopify Function should replace the app you are paying for


Written by the HeapByte engineering team

The test

Ask what the app actually changes at checkout or in the cart. If it modifies discounts, delivery options, payment method availability or cart and checkout validation, there is very likely a Function API that covers the same surface, and the app is a wrapper around functionality Shopify now ships as a first-class primitive.

The giveaway is usually in the app’s own marketing copy: ‘automatically hide payment methods for certain products’, ‘apply tiered discounts based on cart contents’, ‘restrict delivery options by postcode’. These are precisely the categories Shopify Functions were built to cover, and running them through a general-purpose app usually means paying a subscription for logic that could be a few hundred lines of Rust or JavaScript you own outright.

  • Runs inside Shopify’s checkout logic, not as a script tag or client-side override
  • Deterministic input and output, no external API call required at execution time
  • Configuration your team changes rarely — a handful of times a year, not daily

What you gain

Functions run server-side within Shopify’s own execution path, so they cannot be blocked, delayed, or bypassed by client-side conditions the way script-tag based apps sometimes can be — an ad blocker, a flaky third-party script, or a customer on a slow connection has no effect on whether the logic runs correctly.

They are also versioned artefacts you deploy through your own pipeline, which means they can be code reviewed, tested against fixtures, and rolled back with a single command if a release introduces a regression. That is a meaningfully different operating model to toggling settings inside a vendor’s admin panel and hoping the underlying behaviour has not changed with their last update.

There is a cost dimension too, though we would not lead with it. A handful of apps performing checkout logic can add up to a real recurring line item, and replacing two or three of them with owned Functions is sometimes the difference between a five-figure annual app bill and a one-off engineering cost.

What you take on

You now own code, which sounds obvious but is easy to underweight. That means a repository, a deployment path, test coverage, and someone on the team — internal or agency — who actually understands what the Function does and can change it safely. That is a real ongoing cost, and it is the reason we do not recommend replacing every checkout-adjacent app with a custom Function as a matter of course.

The trade is usually worth it when the logic in question is genuinely core to how you sell — a tiered wholesale discount structure, a delivery rules engine specific to your fulfilment network — and rarely worth it when the app is providing commodity behaviour that you would never meaningfully customise beyond what the vendor already offers.

There is also a migration cost to factor in beyond the initial build: merchants moving off an incumbent app need a careful cutover plan, because checkout logic errors are the kind of bug that shows up as lost revenue before anyone notices it in a dashboard.

A worked example

A common pattern we see is a merchant running a dedicated app purely to hide a ‘Pay in 3’ buy-now-pay-later option for orders containing a specific product category, because the BNPL provider’s own settings do not support that granularity. That is a small, deterministic rule with no external dependency at runtime, and it maps almost exactly onto the Payment Customization Function API.

Rebuilding it as a Function typically takes a day or two including tests, replaces a recurring subscription, and — critically — puts the rule under version control where the next person to touch it can see exactly what it does and why, instead of reverse-engineering a vendor’s settings screen.

Insights

Apply this to your store.

An audit turns the general principle into a specific list of changes, ordered by what actually pays back.