TECHNICAL · THEME · OPS · 31 JULY 2026 · 7 MIN READ
Feature flags for a storefront
You almost certainly do not need a flag platform. On Shopify you need a convention, a theme setting, and the discipline to delete a flag once it has done its job.
Use the cheapest mechanism that gives you an off switch someone can reach without a deploy. On a Shopify theme that is usually a theme setting: a checkbox in settings_schema.json, read in Liquid as settings.something_enabled, changed in the theme editor and live immediately with no code change. Reach past that only for the two cases it genuinely cannot serve — a percentage rollout across users, or a flag your back end also has to respect. Most storefront teams reach for a flag platform, get one flag per release, and then never remove any of them, which converts a release tool into permanent conditional complexity nobody can safely delete.
IN SHORT
- A feature flag is an off switch you can reach without a deploy — that is the whole requirement, and most storefront flags need nothing more.
- Shopify documents that global theme settings defined in `settings_schema.json` are read in Liquid via the `settings` object and changed in the theme editor without any code redeploy.
- Section and block settings — `section.settings` and `block.settings` — scope a flag to one template or one instance, which is often the right granularity for merchandising.
- Shopify documents that a setting without an automatic default can end up with no value, which translates to an empty string, so always validate a flag before branching on it.
- Theme app extensions give you a second switch: Shopify documents that they do not edit theme code, and merchants enable or disable them in the theme editor.
- Duplicating a theme is a release channel, not a flag — two flags in two duplicated themes is four themes somebody has to keep in sync.
- Every flag needs a named owner and a removal date written down when it is created, because a flag with no expiry is a permanent branch in your code.
What a flag is actually for
Three distinct jobs get called feature flagging, and conflating them is how teams end up buying a platform for a problem a checkbox solved.
A kill switch. Something new is live, and if it misbehaves you want it off in thirty seconds without a deploy, a build or a developer. This is the job that matters most and the easiest one to satisfy.
A release decouple. The code ships this week, the feature turns on next week when the campaign starts or the supplier confirms. This is scheduling, and it removes the worst pattern in storefront work — the midnight deploy.
An experiment. Half the traffic sees one thing, half sees another, and you measure the difference. This is the only one of the three that genuinely requires per-user assignment, and it is the least common of the three by a wide margin.
If you are honest about which of these you need, most storefront flags turn out to be the first two. Both are satisfied by a boolean somebody can flip in an admin interface.
The Shopify-native mechanisms, cheapest first
Climb this list and stop at the first rung that holds. Each step up costs more to build and more to keep.
- A theme setting. A checkbox in
settings_schema.json, read as{{ settings.new_pdp_gallery }}. Merchant-visible, instant, and reversible by anyone with theme editor access. This covers most kill switches and most scheduled releases. - A section or block setting. Defined in a section's
{% schema %}and read assection.settingsorblock.settings. Use this when the switch belongs to one template or one placement rather than the whole store — a new layout on the collection template only, for example. - A metafield or metaobject. When the flag is per-product, per-collection or per-market rather than global. A "show the size guide" flag belongs on the product, not in theme settings, and a metafield definition makes it a real field with a type rather than a tag convention.
- A theme app extension. Shopify documents that these do not edit theme code and that merchants enable and disable them from the theme editor. If the thing being flagged is an app-delivered feature, this is already a switch and you do not need to build another one.
- A back-end service. Only when the flag has to be respected outside the theme — by a custom app, an integration or a Function — or when you need percentage rollout. This is the first rung that costs real money.
The three ways storefront flags go wrong
The empty string. Shopify documents that a setting without an automatic default value can end up with no value, which translates to an empty string. An empty string is falsy in Liquid, which sounds convenient until the flag you meant to be on by default is off on every theme that has not been re-saved in the editor. Give every flag setting an explicit default, and where the correct behaviour is "on unless turned off", name the setting for the disabling rather than the enabling — hide_x fails safe where show_x does not.
The duplicated theme. Duplicating a theme is the reflex answer and it is a release channel, not a flag. One duplicate is fine. Two features being trialled independently is four combinations, and the moment anything is merchandised in one copy and not the other you are reconciling two codebases by hand. If you find yourself naming themes "live copy — new PDP — with banner", the flag you needed was a checkbox.
The flag that never dies. This is the expensive one. Each flag doubles the number of states the template can be in, and the combinations multiply. Six long-lived flags is sixty-four theoretical configurations, of which you have tested perhaps two. Nobody deletes a flag because nobody is certain what depends on it, so the conditional stays, and three years later a developer is reading a branch that has not evaluated false since 2024.
When a real flag service earns its keep
There are two cases where the Shopify-native mechanisms stop being sufficient, and both are recognisable in advance.
The flag has to be true on both sides. If a custom app, a middleware service or a Shopify Function has to agree with the storefront about whether a feature is on, a theme setting is the wrong home for the truth — the theme editor cannot be the source of record for something your back end reads. Here the flag belongs in the service, with the theme reading it rather than owning it. This is the point at which flagging stops being a theme concern and becomes an application concern, and it is worth being deliberate about where that state lives before you have three systems each with their own copy.
You genuinely need percentage rollout. Not "we want to test which button converts better" — that is an experiment, and your testing tool already does assignment and measurement properly. Percentage rollout is for risk: releasing a rewritten cart to five per cent of sessions because you want to observe error rates before the other ninety-five see it. That is a real requirement and Liquid cannot express it, because a cached page cannot vary per session without help.
Outside those two, buying a platform buys you a nicer dashboard around a boolean you could already toggle, plus another vendor in the request path of every page.
The convention that makes this work
Flagging fails on governance rather than on technology. Four rules, written down once, are worth more than any tool:
- Every flag has an owner and a removal date, recorded when it is created. Not "when we are confident" — a date. The date can move; its absence cannot be audited.
- Name flags for what they do, not for the project.
enable_bundle_buildersurvives a reorganisation.q3_project_atlasdoes not, and in eighteen months nobody will know whether it is safe to remove. - A flag is temporary or it is a setting. If a switch is still there after six months, stop calling it a flag and promote it to a documented, supported theme setting with the naming and grouping that implies. The two things have different lifecycles and pretending otherwise is how the graveyard forms.
- Review the list every quarter and delete something. Fifteen minutes. The deletion is the point — flags accrete silently and the only defence is a recurring appointment.
The honest position
We have added flag infrastructure to Shopify builds and we have removed more than we have added. The pattern is consistent: a team adopts flagging because a release went badly, the tool works, and then the tool becomes the reason nothing is ever finished — a feature is behind a flag, so it is never quite done, so it is never cleaned up.
The version that holds up is small. A handful of theme settings that a merchandiser can reach, one back-end flag where the back end genuinely has to agree, a naming convention, and a quarterly delete. That is a convention rather than a build, it costs an afternoon, and it gives you the thing you actually wanted, which was the ability to turn something off on a Friday afternoon without calling anybody.
Questions this raises
What is a feature flag on an ecommerce storefront?
A switch that changes what shoppers see without a code deploy. On Shopify the usual form is a theme setting — a checkbox defined in `settings_schema.json`, read in Liquid through the `settings` object, and flipped in the theme editor. The defining property is not the technology but the reach: someone non-technical can turn the feature off immediately.
Can I use theme settings as feature flags?
Yes, and for most storefront cases you should. Shopify documents that global settings are accessed via the `settings` object and changed in the theme editor with no redeploy. Give each flag an explicit default, because a setting without an automatic default can end up with no value, which reads as an empty string and is falsy.
Is duplicating a theme a reasonable way to flag a feature?
For exactly one feature at a time, yes. Beyond that it fails quickly: two independent trials mean four theme combinations, and any merchandising change made in one copy has to be repeated in the others by hand. A duplicated theme is a release channel. It is not a flag and it does not compose.
When do I need a real feature flag service?
Two cases. When a back-end service, custom app or Function must agree with the storefront about whether a feature is on — a theme setting should not be the source of record for that. And when you need genuine percentage rollout for risk management, which Liquid cannot express because a cached page cannot vary per session unaided.
Are feature flags the same as A/B tests?
No, though the mechanism overlaps. A flag answers "is this on?"; a test answers "which of these performs better?", which requires random assignment, a measured metric and a stopping rule. Using a flag platform to run tests generally gives you assignment without measurement, which is the worst half.
How many flags is too many?
There is no number, but there is a symptom: when nobody can say with confidence what happens if a particular flag is turned off, you have too many. Each flag doubles the possible configurations and you will only ever have tested a couple of them. Delete something every quarter and the problem never arrives.
NEXT STEP
Free store audit
A senior Shopify engineer reviews your storefront, theme performance and checkout, then sends a prioritised list of fixes.
