0002. PostHog Feature Flag Behavior for Shop/Store Access Control ​
Date: 2026-02-17
Author: Samantha Greenham
Stakeholders: Emily / Appybaras
Status: Accepted
Context ​
The Zuno Store is a new feature with uncertain longevity. We need the ability to:
- Hide the shop tab entirely (e.g. if the feature is deprecated)
- Show the tab but display an unavailable/maintenance screen with access to intercom (e.g. for planned downtime, without confusing users who may have active carts or orders)
We're concerned about failure scenarios — if PostHog goes down or flags are deleted, users on older app versions could access a shop that's been taken down. The safe default should be: show the tab (so users aren't confused), but block access to shop content.
Decision ​
Two PostHog feature flags control shop access:
| Flag | Purpose |
|---|---|
hide-shop-nav | When true, hides the shop tab entirely from the tab bar |
show-shop-content | When true, shows the shop intro screen. When false or missing, shows the unavailable screen |
Both flags default to false when PostHog is unavailable or the flag doesn't exist (useFeatureFlag() returns undefined, coerced to false via !!).
This means the safe default when anything goes wrong is:
- Shop tab visible (so users with carts/orders aren't confused)
- Shop content blocked (unavailable screen shown)
hide-shop-nav | show-shop-content | Result |
|---|---|---|
false | true | Tab visible, shop accessible |
false | false | Tab visible, unavailable screen |
true | true | Tab hidden |
true | false | Tab hidden |
| missing/error | missing/error | Tab visible, unavailable screen |
Alternatives Considered ​
Single flag approach — A single flag like shop-enabled could toggle the entire feature on/off, but wouldn't allow the tab-visible-but-unavailable state needed for maintenance without confusing users who have active orders.
Consequences ​
- Shop content is safely gated by default — PostHog outages or deleted flags result in the unavailable screen, not open access
- Two flags to manage instead of one, but each serves a distinct purpose
- The
hide-shop-navflag name is inverted logic (true = hidden), which could cause confusion — but was chosen so that the defaultfalsekeeps the tab visible