use case

Tier-based feature flagging, explained: flags that know which edition they're in

the short answer

Tier-based feature flagging is a packaging technique where each feature flag has a default state plus an explicit value per product tier (open-source, saas, pro), and every edition of the product builds from the same codebase by resolving the flag set for its tier from committed config — turning the difference between free and paid versions into reviewable data instead of diverging branches.

Classic feature flags answer 'is this feature on for this user right now?'. Tier-based flags answer a quieter, structural question: 'is this feature part of this edition at all?'. Same primitive — a named boolean — pointed at packaging instead of experimentation.

The technique matters most for open-core products, where one codebase ships as a free open-source edition and a paid hosted edition, and where the difference between the two is simultaneously a business model and an engineering liability.

1 codebaseevery tier — open-source, saas, pro — builds from the same commit; only the resolved flag values differ per edition
tierdev.ogbuilds.ai/dashboard
tier·dev
dashboardconnect
+ new flag
dashboard
4 connected repositories — every tier shipping from one codebase.
connect repository
acme/acme-analyticsgithub
3 tiers4 flags
open-sourcesaaspro
olly/openboardgithub
2 tiers7 flags
open-sourcesaas
acme/mailrelaygithub
2 tiers3 flags
open-sourcesaas
olly/schedgitlab
2 tiers5 flags
open-sourcesaas
0 branches to keep in sync — the divergence lives in tiers.json, not in git.

where this happens in the app

tiers are labels on one codebase — every connected repo shows its editions and flag count, and zero long-lived branches keep them in sync.

  1. 1each repo carries its own tiers (open-source, saas, pro) and its own flag matrix.
  2. 2connecting a repo reads metadata only — tier·dev never touches your source code.
  3. 3the divergence between editions lives in tiers.json, not in git topology.

the three parts: tiers, defaults, overrides

A tier is a named edition of your product — open-source, saas, pro — a label on one codebase, never a branch. Each flag carries a default state, which is what any tier gets when you say nothing, and overrides, which are deliberate per-tier exceptions.

The classic shapes: default off with saas overridden on (a paid feature like PRO_DASHBOARD_ENABLED); default on with saas overridden off (community-only behaviour like telemetry prompts); and no overrides at all, which documents that a feature is genuinely universal.

the matrix is the product

Lay flags down the rows and tiers across the columns and you get the artifact that makes the technique work: a complete, readable statement of what every edition contains. 'What exactly does the paid version add?' stops being an afternoon of code archaeology and becomes a screenshot.

From the matrix, tooling like tier·dev generates per-tier config — tiers.json, tiers.yaml, or a dependency-free code module — that you commit. Builds resolve their tier's block; a flag flip is a one-line diff someone approves.

when tier-based flagging is the wrong tool

If you need percentage rollouts, user targeting, or instant kill switches, you need runtime flag delivery — a different job (see the LaunchDarkly comparison below). And if you only ship one edition, plain feature flags cover you; tiers earn their keep the day your pricing page splits the product into versions.

frequently asked

is this the same as a freemium plan gate?
Related but lower in the stack. Plan gates check a customer's subscription at runtime inside one deployment; tier flags decide what each shipped edition contains in the first place. SaaS plans often layer plan gates on top of the saas tier's build.
how many tiers do products actually use?
Two or three covers almost everyone: open-source + saas is the core open-core shape, with pro or enterprise as a third column. Because a tier is one more column of values — not a new build pipeline — adding one later is cheap.
what flag types does tier-based flagging need?
Booleans cover the packaging job almost entirely — a feature is in an edition or it isn't. Numeric limits (seats, quotas) usually belong to runtime plan gates rather than build-time packaging.

Last updated June 12, 2026

ready to try tier·dev?

connect a repo