Define your configuration
Segments
Segments are named, reusable conditions on attributes, segments, features and variables. Feature rules, force entries and variable overrides refer to them by key, so an audience such as the Netherlands is defined once.
Create a segment#
Each segment is a YAML file in segments/. The file name is its key. The project that init creates already declares netherlands:
description: The Netherlandsconditions: - attribute: country operator: equals value: nlIt matches any context whose country is nl. Both description and conditions are required. To group keys in directories, see Namespaces.
Refer to the segment by its key:
description: Checkout redesignbucketBy: userIdrules: - key: netherlands conditions: netherlands percentage: 100 - key: everyone conditions: '*' percentage: 25'*' matches every context, so you do not need a segment for everyone. Rules can also combine segment keys with and, or and not, as Features shows. Variable overrides and force entries take segments the same way.
Name each segment after the audience your team talks about, such as payingAccounts or largeAccounts, so a rule reads like the release plan behind it. A change to a segment reaches every feature and variable that refers to it. That makes the segment the one place to update an audience, and a change to review with care. Check what depends on it first with find usage.
Write conditions#
An attribute leaf compares one value in the context:
| Property | Description |
|---|---|
attribute | An attribute key. For an object attribute, a dotted path such as account.seats selects a property. |
operator | How to compare. The operator reference lists each one with the types it accepts. |
value | What to compare against, of the attribute's type. Omit it for exists, notExists, isNull, notNull, empty and notEmpty. |
regexFlags | Optional flags for matches and notMatches, such as i to ignore case. |
These segments use the plan and account attributes declared in Attributes:
description: Paid and enterprise accountsconditions: - attribute: plan operator: in value: - paid - enterprisedescription: Accounts with 50+ seatsconditions: - attribute: account.seats operator: greaterThanOrEquals value: 50Linting checks every value against the attribute's declaration, so piad fails where plan only allows free, paid and enterprise. In attribute conditions, in and notIn only work with string attributes. For numbers, combine equals conditions with or.
Combine conditions#
A list under conditions matches when every condition in it matches. Group conditions with and, or and not to say more:
| Group | Matches when |
|---|---|
and | Every condition in it matches |
or | At least one condition in it matches |
not | The conditions in it do not all match |
Groups nest. This segment matches Dutch accounts that are on enterprise or have 50 or more seats:
description: Dutch enterprise or 50+ seatsconditions: - attribute: country operator: equals value: nl - or: - attribute: plan operator: equals value: enterprise - attribute: account.seats operator: greaterThanOrEquals value: 50Exclude with not#
The conditions inside not are combined with and before the result is negated. So this matches everyone except Dutch enterprise accounts. A Dutch account on free still matches, and so does a German enterprise account:
# ...conditions: not: - attribute: country operator: equals value: nl - attribute: plan operator: equals value: enterpriseTo exclude every context that matches either condition, put an or group inside not:
# ...conditions: not: - or: - attribute: country operator: equals value: nl - attribute: plan operator: equals value: enterpriseEach group needs at least one condition. Empty arrays and groups are lint errors and return false at runtime. Write conditions: '*' to match every context. The wildcard is valid only as the whole expression.
Reference other definitions#
Segments accept the same four leaf kinds as every other selector. Reuse netherlands, require live chat and compare maintenance mode:
description: Dutch chat outside maintenanceconditions: - netherlands - feature: liveChat - variable: maintenanceMode operator: equals value: falseA feature variable leaf adds feature to variable. Mix these leaves inside and, or and not too. Lint rejects direct and indirect cycles, including a feature rule that reaches its own flag through a segment. Runtime segment cycles fail the whole evaluation with error.
Test a segment#
A segment spec states which contexts should match. Write one for every segment with more than a single condition:
segment: prioritySupportassertions: - description: Dutch enterprise account context: country: nl plan: enterprise expectedToMatch: true - description: Large Dutch account context: country: nl plan: paid account: locale: nl-NL seats: 80 expectedToMatch: true - description: German enterprise account context: country: de plan: enterprise expectedToMatch: falsenpx featurevisor test --entity-type=segmentWhen a segment depends on a feature or variable, directly or through another segment, add environment to each assertion if the project configures environments. Optional at controls dependency bucketing, while stickyFeatures and stickyVariables pin dependency results. Segment checks inside other specs inherit those settings from their enclosing assertion. Attribute only segments do not need an environment.
Each assertion covers one branch: the enterprise plan, the seat count, and a country outside the Netherlands. See Testing for checks across several entities.
Datafiles#
A datafile includes a segment only when a feature or global variable in its target uses it, in a rule, a force entry or an override. The SDK evaluates them while it resolves those features and variables.
Find usage and duplicates#
Before changing a segment, see what depends on it. The CLI lists the features, global variables and other segments that use a segment, the segments nothing uses, and segments with identical conditions:
npx featurevisor find-usage --segment=netherlandsnpx featurevisor find-usage --unused-segmentsnpx featurevisor find-duplicate-segmentsArchiving#
Set archived: true on a segment you no longer use:
archived: truedescription: Accounts with 50+ seatsconditions: - attribute: account.seats operator: greaterThanOrEquals value: 50An archived segment is left out of every datafile, where a reference to it would never match, and not around it would match everyone. Linting stops an active feature, global variable, segment or spec from still referring to it. Remove its references first, using find-usage above.
Lint checks an archived segment for its shape only, without resolving the attributes and definitions its conditions name. Keep the file rather than deleting it, so the key is not reused with another meaning. You can list archived segments afterwards:
npx featurevisor list --segments --archivedPromotable#
In a project that uses sets, a segment can protect its existing destination definition from later promotions by setting promotable: false at the top level:
description: The Netherlandspromotable: falseconditions: - attribute: country operator: equals value: nlIf the destination segment exists, it remains unchanged when either the source or destination segment has this field. A missing destination segment is still created and retains promotable: false. Individual conditions cannot be protected separately.
Related#
- Attributes, which segments compare against
- Condition operators
- Segments in feature rules
- Group segments in directories

