The problem with copy-pasted rules
Say you want "beta testers" or "pro plan customers in the EU" to see early access to new features. The first flag you write that rule into is easy. The tenth flag is where it breaks down — someone adds a new beta tester and has to remember every flag that needs updating, or a rule gets typed slightly differently in one flag and that group's experience quietly diverges from the rest.
A segment is that audience defined once, by name, and referenced from as many flags as you need. Update the definition in one place, and every flag using it picks up the change immediately — no hunting through your flag list for stale copies of the same rule.
What you get from naming an audience
"Pro plan in EU" means the same thing everywhere it's used — no flag silently targeting a slightly different version of your intended audience.
Your beta group grows, or a customer graduates out of an early-access cohort — change the segment, and every flag referencing it reflects that instantly.
A segment still referenced by any flag can't be deleted out from under it — you'll never accidentally break a rule by removing the audience it depends on.
"targets: pro-eu" tells the next person reading a flag what audience is in play, without them having to decode a wall of inline conditions.
Defining and using one
- GET /segments — list segments for the org
- GET /segments/{key} — fetch one
- POST /segments — create
- PUT /segments/{key} — update rules
- DELETE /segments/{key} — refuses if any flag still references it
POST /segments
{
"key": "pro-eu",
"name": "Pro plan in EU",
"rules": [
{ "attribute": "plan", "op": "eq", "value": "pro" },
{ "attribute": "country", "op": "in", "value": ["DE","FR","ES","IT","NL"] }
]
}Reference the segment by key from any flag rule, and it evaluates exactly as if its conditions were written directly into that flag — a segment is a name for a set of rules, not a separate system to reason about.