Shopify Functions and metafields: customizing without an app for every rule

There is a familiar line item on most Shopify profit and loss statements: a column of small monthly charges, each one bought to solve a single rule. One app enforces a minimum order quantity. Another hides a shipping method from PO boxes. A third stops a wholesale customer from using a retail discount code. Individually they cost less than lunch. Together they can run past $400 a month before anyone notices.

That stack made sense when the platform could not express those rules natively. It makes much less sense now. Shopify Functions let a merchant write discount, shipping, payment and validation logic that runs inside Shopify’s own checkout, and metafields plus metaobjects let structured data live on products and collections without a third party storing it. The question for 2026 is no longer whether the platform can do it. It is whether your team can maintain it.

This piece walks through what Functions actually cover, where metafields fit, how the two-year cost compares against app subscriptions, and the failure modes that catch teams who build custom logic and then lose the person who wrote it. If you are still deciding which platform to run at all, our broader guide on how to choose the right e-commerce platform for your store covers the layer above this one.

In short

  • Functions are not “no app”. A Function ships inside an app, usually a custom app you build and install yourself, so the real saving is the subscription and the vendor dependency, not the app concept.
  • Discounts, delivery and payment customization, cart transforms and validation are the main Function APIs. Plan availability differs by API, and Shopify’s developer documentation is the only reliable source for which ones your plan can run.
  • Metafields and metaobjects handle structured content such as size charts, care instructions, specification tables and store locators, which removes a whole class of content apps.
  • The break-even is usually two to four replaced apps. One $19 app almost never justifies a build. Four apps at $40 each, running for two years, usually does.
  • Maintainability is the real risk. Custom logic with no documentation and no second person who understands it is more expensive than the subscription you cancelled.

What Shopify Functions replaced

For years, the only way to run custom logic inside Shopify’s checkout was Shopify Scripts, a Ruby-based system restricted to Plus merchants. Scripts were powerful and genuinely useful, but they were tied to the old checkout.liquid architecture, which Shopify spent several years retiring. Functions are the replacement, and they are built on a completely different foundation.

From Scripts to WebAssembly

A Shopify Function is a small program compiled to WebAssembly and executed on Shopify’s infrastructure at the moment a cart or checkout is evaluated. You can write it in Rust, JavaScript or any language that compiles to a Wasm target, with Shopify’s own tooling leaning toward Rust and JavaScript. The runtime is sandboxed and deterministic, which is exactly what you want in a checkout path.

The practical difference from an app is latency and reliability. A traditional app enforcing a cart rule has to receive a webhook or an API call, process it on its own servers, and respond. A Function runs inside Shopify. There is no network hop to a vendor who might be having a bad afternoon.

Shopify’s developer documentation sets hard execution budgets for Functions: a fixed instruction limit per invocation (documented in the millions of instructions) plus caps on input and output payload size. Those figures have moved more than once since launch, so treat any number you read in a blog post, including this one, as a prompt to check Shopify’s Functions documentation rather than as settled fact.

Why the checkout rewrite forced the change

The move was not optional. Shopify deprecated checkout.liquid in stages, and the Scripts system went with it. Merchants who had years of Ruby logic sitting in Script Editor had to rebuild it as Functions or lose it, and a lot of agencies spent 2025 doing exactly that migration work.

If your store still has unfinished business from that transition, our walkthrough of Shopify checkout extensibility and what replaced checkout.liquid covers the UI side of the same rewrite. Functions handle the logic; checkout UI extensions handle what the customer sees. Most real projects touch both.

What Functions deliberately do not do

Functions cannot call external APIs mid-execution. They cannot read arbitrary store data outside the input Shopify hands them. They cannot write data back. That is a design decision, not an oversight: a checkout that waits on a third-party lookup is a checkout that fails when the third party does.

This matters when you scope a project. Any rule that depends on live data from an ERP, a tax engine or a real-time inventory feed is not a pure Function problem. You can often pre-sync that data into metafields on a schedule and let the Function read the metafield, which is a pattern worth knowing before you conclude the platform cannot do what you need.

Discount, shipping and validation logic in practice

The Function APIs are narrow by design. Each one plugs into a specific decision point and returns a specific shape of answer. Knowing which API covers which problem saves a lot of wasted scoping.

Discounts

Discount Functions cover product discounts, order discounts and shipping discounts. This is where most merchants start, because the native discount engine runs out of road quickly. Buy three of any item in this collection and get the cheapest free. Tiered volume breaks that change at 10, 25 and 50 units. A loyalty tier stored on the customer record that unlocks a percentage off.

Discount combination rules are part of this API too, which is the detail that usually decides whether a Function is needed. Deciding that an order discount can stack with a shipping discount but not with a product discount is native behaviour in Functions and was a notorious pain point before.

Delivery and payment customizations

Delivery customization Functions reorder, rename or hide shipping methods at checkout. Hiding express shipping for oversized items, renaming a carrier rate to something a customer understands, or suppressing a pickup option for a location that is closed are all small rules that merchants used to buy whole apps for.

Payment customization Functions do the same for payment methods. Hiding cash on delivery above a cart value threshold, or suppressing a particular wallet for international orders, is a two-condition Function rather than a subscription. Plan availability for these two APIs has historically been narrower than for discounts, so confirm it against the current documentation before you scope a build.

Cart transforms and validation

Cart Transform Functions can merge, expand or update line items. The classic use is bundles: a customer adds one bundle product and the transform expands it into component SKUs so inventory and fulfilment stay accurate. The reverse pattern, collapsing components into a single displayed line, is also common.

Cart and checkout validation Functions block progress when a rule is broken: minimum order quantity, restricted products for a given customer tag, a maximum weight per shipment, a region exclusion. They return an error message the customer actually sees, which is why the message text deserves as much thought as the logic.

Function API Typical app category it replaces Common use
Product, order and shipping discounts Volume discount, BOGO, tiered pricing apps Quantity breaks, bundle pricing, loyalty tiers
Delivery customization Shipping rule and rate-hiding apps Hide or rename methods by product, zone or weight
Payment customization Payment method hiding apps Suppress COD above a threshold, restrict wallets by market
Cart transform Bundle and kitting apps Expand a bundle into components at checkout
Cart and checkout validation Order limit and B2B rule apps Minimum quantities, restricted SKUs, weight caps
Fulfilment and order routing Multi-location routing apps Pick the fulfilment location by rule rather than default priority

The pattern across that table is consistent. These are all rules, not features. Rules belong in the platform. Features, such as a subscription billing engine or a review collection flow with its own email sequence, do not, and no amount of Function enthusiasm changes that.

Metafields and metaobjects for structured content

Functions solve logic. Metafields and metaobjects solve data. They are separate systems that end up in the same project because the second one usually feeds the first.

What metafields actually give you

A metafield attaches typed custom data to a resource: products, variants, customers, orders, collections, pages, even the shop itself. The key word is typed. Defining a metafield as a measurement, a date, a file reference or a product reference means Shopify validates the input and your theme can render it without defensive string parsing.

Standard metafield definitions cover common retail needs out of the box, including care instructions, material composition and dimensions. Custom definitions handle everything else. Both appear in the admin as proper form fields, which is the detail that decides whether a merchandiser will actually fill them in.

Metafields are also readable by Functions. A volume discount tier stored on the product, or a customer tier stored on the customer, becomes the input a Discount Function reads. That combination, data in metafields and logic in Functions, is the architecture most mature Shopify builds converge on.

Metaobjects for content that is not a product

A metaobject is a reusable structured record that is not tied to a single product. Size charts, store locations, ingredient entries, designer profiles, FAQ entries and shipping policy blocks are all natural metaobjects. You define the fields once, create entries, then reference those entries from products or render them in the theme.

The practical win is that one size chart serves 200 products instead of being duplicated into 200 product descriptions. When the chart changes, it changes once. The content apps that used to sell exactly this capability are now hard to justify.

Where this stops being enough

Metafields and metaobjects are storage and rendering. They are not a workflow engine, they do not send email, and they have no scheduling layer. If your requirement includes approval steps, versioned content with a publish date, or syndication to another channel, you are back in app territory or in a headless setup with a separate content system.

Requirement Metafields Metaobjects Third-party app
Data attached to one product Best fit Overkill Unnecessary
Shared record used by many products Poor fit, duplicates data Best fit Unnecessary
Input for a Discount Function Best fit Workable via reference Not readable by Functions
Editorial workflow and approvals Not supported Not supported Best fit
Scheduled publishing of content Not supported Not supported Best fit
Rendering in an Online Store 2.0 theme Native Native Usually via app block

When a Function is cheaper than an app subscription

The honest answer is that it depends on three numbers: how many apps the build replaces, what those apps cost, and what a developer hour costs you. Teams get this wrong in both directions, building $8,000 of custom logic to kill a $19 app, or paying $500 a month for six years rather than spend one week of developer time.

Start with the stack, not the idea. List every app whose entire job is enforcing a rule. Volume discount apps, order limit apps, shipping rate hiders, payment method hiders, bundle apps and B2B rule apps are the usual suspects. Add up the monthly cost of only those, ignoring apps that do real work such as email, reviews, search or accounting sync.

If that number is under $50 a month, the build almost never pays back inside two years once you count maintenance. Between $50 and $150 a month it becomes a judgement call that hinges on how stable your rules are. Above $150 a month, consolidation into a single custom app with several Functions is usually the better economics.

The cost most teams forget

App subscriptions are not the only cost of the app approach. Each app adds a vendor who can raise prices, get acquired, break on a Shopify API version bump, or shut down. Each one also holds a piece of your business logic in a place you cannot read.

Against that, Functions carry their own hidden cost: you now own the code. Shopify will not fix your discount logic at 2am on Black Friday. That trade, vendor risk for ownership risk, is the real decision, and it depends far more on whether you have reliable development capacity than on the spreadsheet.

Plan thresholds change the maths

Several Function APIs have had plan restrictions, and some capabilities have been Plus-only at various points. If a Function you need sits behind a plan upgrade, the comparison is no longer app fees versus developer time. It becomes app fees versus developer time plus the upgrade, which is a much bigger number. Our breakdown of Shopify versus Shopify Plus and when the upgrade is worth it works through where that line actually falls.

Developer time versus app fees over two years

Here is a worked comparison for a store replacing four rule apps. The developer rate assumed is $120 an hour, which sits in the middle of the range for an experienced Shopify partner in North America or Western Europe as of 2026. Adjust it to what you actually pay, because this number drives the whole result.

Line item App stack Custom app with Functions
Four rule apps at $45 each per month $180 per month $0
Initial build (28 hours at $120) $0 $3,360
Configuration and testing 8 hours, $960 Included above
Maintenance across 24 months Vendor handled 10 hours, $1,200
Subscription cost across 24 months $4,320 $0
Two-year total $5,280 $4,560
Cost in year three onward $2,160 per year Roughly $600 per year

Two things stand out. First, the two-year totals are close enough that the decision is not really financial at this scale; it is about risk tolerance and capacity. Second, the gap widens sharply after year two, because subscriptions keep running while a stable Function costs almost nothing to leave alone.

Change one input and the picture flips. Replace two apps at $19 instead of four at $45 and the app stack wins comfortably. Push the build to 60 hours because the rules are genuinely complex and the app stack wins again. Run the same four apps for five years and Functions win by thousands.

The variable nobody models

The input that moves the result most is rule churn. If your promotional logic changes every quarter because marketing keeps inventing new mechanics, every change is a developer ticket rather than a settings screen. A well-built Function can expose its parameters through metafields or app settings so a merchandiser changes thresholds without a deploy, but that flexibility has to be designed in and it adds hours to the initial build.

Worth noting too that app costs scale with your Shopify plan on some pricing models, and your plan itself is a moving number as you grow. Our breakdown of Shopify pricing for stores of every size is the place to sanity-check what the platform layer costs before you optimise the app layer.

Performance and checkout stability considerations

Running logic inside the checkout is a privilege with conditions attached. Shopify enforces those conditions hard, and understanding them prevents a category of nasty surprises.

The execution budget is not negotiable

A Function that exceeds its instruction limit does not degrade gracefully. It fails, and depending on the API, the result is either no discount applied or a checkout that cannot proceed. Shopify’s documentation is explicit that Functions must complete within a tight budget, which rules out naive approaches such as looping over every variant in a large catalogue.

In practice this means shaping the input. Function input is defined by a GraphQL query you control, so request only the fields you need. A Function that pulls three metafields for the cart’s line items will comfortably stay inside budget; one that pulls every metafield on every product will not.

Test against real cart shapes

The cart that breaks a Function is rarely the one in the test plan. It is the 47-line wholesale order, the cart with a gift card and three discount codes, or the international order with a mixed-currency presentment. Build those carts deliberately in a development store before anything touches production.

Shopify’s CLI supports running a Function against saved input files, which makes regression testing genuinely practical. Saving the awkward carts as fixtures and rerunning them after every change is a 20-minute habit that prevents a very bad Friday.

Failure behaviour and the discount cap

Decide explicitly what happens when the logic cannot produce an answer. For discounts, failing open means the customer pays full price and complains. For validation, failing open means an invalid order enters fulfilment. Neither is automatically correct, and the right choice differs per rule, so write it down rather than letting the default decide.

There are also structural limits worth checking before you design around them, including how many discount Functions can run on one order and how multiple Functions of the same type interact. These details sit in the Functions documentation and have changed across API versions, which is the general theme of this whole section.

Keeping a maintainable setup as staff change

This is where custom Shopify logic quietly goes wrong, and it has very little to do with code quality. A perfectly written Function with no documentation is a liability the moment its author leaves.

Write down why, not what

The code says what the rule does. Nothing says why it exists. A comment recording that the 12-unit minimum on a given collection comes from a supplier contract signed in 2025 is worth more than any amount of tidy formatting, because the next developer will otherwise remove it as an arbitrary restriction.

Keep a single plain-language document listing every Function, the business rule it enforces, who asked for it, and what should happen if it fails. Three pages is enough. The test is whether a new developer can read it on day one and know what not to touch.

Expose the knobs to non-developers

Hard-coded thresholds guarantee a developer ticket for every change. Storing thresholds in shop-level metafields or in the custom app’s own settings means a merchandiser changes the volume break from 25 to 20 units without a deploy. This is the single highest-return design decision in a Functions project.

The same principle applies to the theme layer. Logic in Functions, content in metaobjects and presentation in theme settings keeps each change in the hands of whoever should be making it. Our guide to choosing a Shopify theme that converts without custom code makes the same argument from the front-end side.

Keep the custom app in source control and keep a second pair of eyes

A custom app containing Functions is a real codebase. It belongs in a repository with the deploy process documented, not on one laptop. Shopify’s CLI handles versioning and deployment, and Functions deploy as app versions you can roll back, which is a genuine safety net if you actually use it.

Make sure at least two people can deploy. A single point of failure in your checkout logic is a worse operational risk than the app subscriptions you cancelled, and it is the most common reason a Functions migration ends up being reversed a year later.

A short checklist before you build

Before committing to a Functions project, work through six questions. If more than two come back unfavourable, keep the apps.

  1. How many apps does this actually replace? One rarely justifies a build. Three or more usually does.
  2. What do those apps cost per month? Under $50 combined, the payback period is too long to bother.
  3. How stable are the rules? Logic that changes monthly needs configurable parameters, which adds hours.
  4. Does any rule need live external data? If yes, Functions alone will not cover it and you need a sync layer.
  5. Is the required Function API available on your plan? Verify against current documentation, not a blog post.
  6. Who maintains it in 18 months? If the honest answer is nobody, the subscription is the cheaper option.

That last question carries the most weight. Technical capability is the easy part of this decision, and the merchants who regret the move are almost never the ones who misjudged the code. They are the ones who did not plan for the handover.

For teams still weighing whether Shopify is the right foundation for this kind of customization in the first place, or comparing it against platforms with different extensibility models, our guide to choosing the right e-commerce platform sets out the trade-offs across the main options.

One closing note on figures: Shopify’s plan availability, execution limits and API surface for Functions have all changed repeatedly since launch, and any specific number in this article reflects the position as of October 2026. Check Shopify’s developer documentation for the current state before you scope a build against it.

FAQ on Shopify Functions

Do Shopify Functions require an app?

Yes. A Function is packaged inside an app and deployed through it, typically a custom app you build for your own store rather than one from the App Store. The saving is the recurring subscription and the third-party dependency, not the app concept itself, so “no app for every rule” is a more accurate framing than “no apps”.

Are Shopify Functions available on every plan?

Availability varies by Function API and has changed over time. Discount Functions have been the most widely available, while some customization APIs have carried plan restrictions. Check Shopify’s current developer documentation for your specific API before scoping any work, because this is exactly the detail that invalidates a project estimate.

What happened to Shopify Scripts?

Scripts were tied to the legacy checkout architecture that Shopify retired in stages, and they were deprecated alongside it. Merchants running Script Editor logic had to rebuild it as Functions. If you still have unmigrated Scripts logic, that work is overdue rather than optional.

Can a Function call an external API?

No. Functions run in a sandboxed environment with no network access, which keeps checkout fast and predictable. If a rule needs external data, sync that data into metafields on a schedule and have the Function read the metafield instead. That pattern covers most cases that initially look impossible.

How long does a typical Functions build take?

A single straightforward rule, such as hiding a shipping method by product tag, is often a day or two including testing. A consolidated custom app replacing four or five apps with configurable parameters is more commonly in the 25 to 40 hour range. Complex discount stacking logic can run well past that.

What is the difference between a metafield and a metaobject?

A metafield attaches data to an existing resource such as a product or customer. A metaobject is a standalone structured record that many resources can reference, which makes it right for anything shared, such as a size chart used across a whole collection. Use metafields for product-specific data and metaobjects for reusable content.

Can a merchandiser change Function settings without a developer?

Only if the Function was designed for it. Thresholds and parameters stored in metafields or app settings can be edited in the admin, while hard-coded values require a code change and a deploy. Insist on configurable parameters during scoping, because retrofitting them later costs more than building them in.

What happens if a Function fails during checkout?

Behaviour depends on the API. A failed discount Function generally means the discount does not apply, while a failed validation can block the checkout. Decide the intended failure mode for each rule during design and test it deliberately, rather than discovering it during a sale.

Is it worth replacing just one app with a Function?

Usually not. The build, testing and ongoing ownership cost of a single Function rarely beats a $20 or $30 subscription over a reasonable horizon. The economics work when one custom app consolidates several rules, because the fixed setup cost is spread across all of them.