Skip to main content
The hierarchy is the ordered list of values your application passes when it queries a feature config. Foff uses those values to find the most specific override that matches, then falls back toward the default if no match is found. This model lets a single feature flag serve thousands of users while still supporting precise, targeted overrides.

The resolution algorithm

When you query a feature, Foff walks the hierarchy from the most specific combination of values down to the least specific, checking for an override at each step. The first match wins. If no override matches any level, Foff returns the feature’s default value. For a hierarchy of [level-1, level-2, level-3], the resolution order is:
  1. level-1 + level-2 + level-3 (full path — most specific)
  2. level-1 + level-2
  3. level-1
  4. (feature default) (least specific — always the final fallback)

Step-by-step example

Suppose your scope uses the hierarchy Organization → Team → User. Your application fetches dark-mode for the values ["org-1", "team-a", "user-123"].
Foff looks for an override scoped to exactly org-1, team-a, and user-123. This would be a user-specific override — the most granular possible. If found, this value is returned immediately and resolution stops.
No user-level override was found. Foff checks for a team-level override scoped to org-1 and team-a. If an override exists here, it applies to every user in that team (unless they have a user-specific override). If found, this value is returned and resolution stops.
No team-level override was found. Foff checks for an organization-level override scoped to org-1. If found, this applies to every user in the organization who doesn’t have a more specific override. If found, this value is returned and resolution stops.
No organization-level override was found. Foff returns the feature’s default value — the one you set when you created the feature. This is the ultimate fallback and always applies when no override matches.

Why this model is powerful

The hierarchy model means you write your flag logic once and Foff handles the targeting automatically. Consider what this enables:
  • Roll out to one org: Add an override at org-1 to enable a feature for every user in that organization — without touching any other org.
  • Exclude one team: Add an override at org-1 + team-a that disables a feature, even if the org-level override enables it for everyone else.
  • Target a single user: Add an override at org-1 + team-a + user-123 to give one user a different experience without affecting anyone else.
You can control the experience for thousands of users with a handful of overrides, and the specificity ordering ensures that the right value always takes precedence.
Use hierarchy values that match your actual data model identifiers — database IDs, slugs, or stable string keys work well. Avoid display names or values that might change over time, since override matching is exact and case-sensitive.

Reference: resolution order table

StepHierarchy pathDescription
1All levels combinedMost specific — exact match for this entity
2All levels except the lastParent-level override
Continues up the hierarchy
NFirst level onlyTop-level organization override
N+1(none)Feature default — always the final fallback

Overrides

Learn how to create overrides and what values you can set at each hierarchy level.

Scopes

Understand how scopes define the hierarchy model for a group of flags.