Segments
A segment is a named, reusable audience. Define "enterprise accounts" once, then reference it from every flag that cares, instead of copying the same conditions into a dozen rules.
How membership is decided
A segment has three inputs, checked in this order:
- Excluded keys — if the user's key is here, they are out. This wins over everything.
- Included keys — if the user's key is here, they are in.
- Rules — the user is in if any rule matches.
If none of the three puts them in, the user is not in the segment.
The user key
Included and excluded lists are matched against a single identifier resolved
from the context: key, falling back to userId, then
email. If none are present the key is empty and the user can
never appear in either list, though rule-based membership still applies.
userId then email, and ignores key. If
you identify users with key alone, segments will work and
percentage rollouts will bucket every one of those users identically. Send
userId to be safe on both.
Referencing a segment from a flag
Use the segment_match operator. Its value is a segment key, or
a list of them, and the user matches if they are in any of them.
The attribute field is ignored by this operator; the convention
is to set it to segmentKey to satisfy schema validation.
{
"name": "enterprise gets the new dashboard",
"conditions": [
{ "attribute": "segmentKey", "operator": "segment_match", "value": "enterprise-accounts" }
],
"serveValue": true,
"rolloutPercentage": null
} Combine a segment with ordinary conditions to narrow it further:
"conditions": [
{ "attribute": "segmentKey", "operator": "segment_match", "value": ["enterprise-accounts", "design-partners"] },
{ "attribute": "country", "operator": "in", "value": ["US", "CA"] }
] Both conditions must hold: the user must be in either segment and in one of those countries.
Segment shape
interface CachedSegment {
key: string;
/** Explicit user keys that are always in. */
included: string[];
/** Explicit user keys that are always out — takes precedence over included. */
excluded: string[];
/** Rule-based membership: a user matches if ANY rule matches. */
rules: { conditions: RuleCondition[] }[];
} Gotchas
- An unknown segment key matches nobody. Referencing a segment that doesn't exist, or was deleted, evaluates to false rather than erroring. A typo therefore looks like an empty audience, not a failure.
- A segment rule with no conditions matches nobody. This is deliberate: an empty rule silently including every user would be a dangerous default. Note this is the opposite of a flag rule with no conditions, which matches everyone.
- Segments are environment-scoped, like flags. A segment in staging is a separate object from the one in production.
When to use one
- Reuse: the same audience gates three or more flags.
- Churn: the membership list changes more often than the flags that reference it, such as a beta cohort.
- Allow/deny lists: a handful of named accounts, via
includedandexcluded, with no conditions at all.
For a one-off audience used by a single flag, an inline condition is simpler and easier to read. Reach for a segment when the audience outlives the flag.