Trait-Based Segmentation in Flagsmith
A complete, plain-English guide to showing the right feature to the right people: what traits are, how segments use them, how rules are evaluated, and how to design, test and run trait-based targeting safely at scale.
Imagine a bakery that makes one special cake every day. On Monday the cake is for children, on Tuesday for people who like chocolate, on Wednesday for customers who have visited more than ten times. The baker does not decide this by guessing. She keeps a small card for every regular customer, with a few facts written on it: age group, favourite flavour, number of visits. When a customer walks in, she glances at the card and knows which cake to offer.
Those little facts on the card are what Flagsmith calls traits. The rule “customers with more than ten visits” is what Flagsmith calls a segment. Put the two together and you get trait-based segmentation: the ability to turn features on, off or change their values for groups of users, based on facts you know about them.
Flagsmith is a tool that lets software teams switch features on and off without releasing new code, using switches called feature flags. A plain flag treats everybody the same. Trait-based segmentation makes a flag smart: the same flag can say “yes” to paying customers, “no” to free users, and “yes, but with a smaller limit” to people on an old version of the app.
In this guide you will learn what traits and segments are, where trait data comes from, how rules are written and evaluated, how to design a clean set of traits, how to test and monitor segments, and how to keep personal data safe. We will use everyday comparisons and examples from well-known companies along the way.
Flagsmith changes over time. Operator names, plan limits, SDK behaviour and dashboard labels can differ between versions. Treat this guide as the mental model, and confirm fine details in the official Flagsmith documentation for the version or plan you use.
1Why Different Users Need Different Flags
A flag that treats everyone alike is useful. A flag that treats the right people differently is far more powerful.
The limit of a simple switch
A basic feature flag has two answers: on for everybody or off for everybody. That is fine for a quick experiment or an emergency stop. But real products have many kinds of users. Some pay and some do not. Some live in India and some in Brazil. Some use the newest app and some use a version from two years ago. Some are employees testing, and some are customers paying their bills.
If every one of those groups must see the same thing, the team is forced into awkward choices. Either they delay a feature until it is ready for everyone, or they release it to everyone and hope. Neither is comfortable.
What teams really want
Teams want to say things like these, in plain language:
- “Show the new dashboard only to our own staff for now.”
- “Give premium customers a higher upload limit.”
- “Turn off the new payment screen for people on app versions older than 5.0.”
- “Release the feature in Canada first, because the support team there is ready.”
- “Let customers who signed up this month try the beta.”
Each sentence mentions a fact about the user: staff or not, plan, app version, country, signup date. Those facts are exactly what traits store.
A cinema does not show the same film to everyone in the building. Children go to the cartoon, adults to the thriller, and members get a seat in the quiet screen. The ticket tells the usher which room to send you to. A trait is like information on the ticket, and a segment is like the room.
Benefits in one glance
Smaller blast radius
A change reaches a small, chosen group first, so a mistake hurts fewer people.
Plan-based features
Entitlements follow the plan a customer pays for, without hard-coding rules in every app.
No new release needed
Change who sees a feature by editing a rule, not by deploying code.
Targeted experiments
Test a new idea on one kind of customer and compare it with another.
Gradual rollouts
Support teams meet new questions in small waves, not in one flood.
Regional rules
Features can be turned on or off by country where local rules require it.
2Flagsmith Basics: Features, Environments and Identities
Before we add traits, we need to know the parts of Flagsmith that traits attach to.
Organisations, projects and environments
Flagsmith organises everything in three layers. An organisation is usually a company or a team. Inside it live projects, each normally one product. Inside each project are environments, such as Development, Staging and Production. A feature is a named switch defined once per project. What the switch does, whether it is on and what value it carries, is stored separately in each environment.
Remote configuration
A flag can also carry a value, such as a number or a piece of text. This is often called remote configuration. For example, a feature called “upload_limit_mb” might hold the number 25 for ordinary users and 100 for premium users. Segments can change that value for different groups.
What is an identity?
An identity in Flagsmith is a record that stands for one user of your product. It has an identifier, which is a string your system chooses, such as a customer number or a hashed email. Flagsmith uses the identifier to remember that user and give consistent answers across visits.
Identities belong to one environment. The same person has separate identity records in Development and in Production, because the environments are separate rooms.
flowchart TD
ORG["Organisation"] --> PRJ["Project: Shopping App"]
PRJ --> FEAT["Features: named switches"]
PRJ --> SEG["Segments: reusable rules"]
PRJ --> ENV["Environment: Production"]
ENV --> FS["Feature states per environment"]
ENV --> SO["Segment overrides per environment"]
ENV --> ID["Identities"]
ID --> TR["Traits: facts about each identity"]
ID --> IO["Identity overrides"]
A map of ownership
| Thing | Lives at | Plain meaning |
|---|---|---|
| Feature | Project | The named switch |
| Segment | Project | A reusable group defined by rules |
| Feature state | Environment | On or off, plus value, in one environment |
| Segment override | Environment | A different setting for one segment in one environment |
| Identity | Environment | One user record |
| Trait | Environment, on an identity | One fact about that user |
| Identity override | Environment | A special setting for one named user |
Segments are written once per project. What a segment does to a flag is decided separately in each environment. That is why a segment can exist everywhere and still affect only production.
3What Is a Trait?
A trait is the smallest and most important building block of targeting. Let us look at it closely.
A plain definition
A trait is a single named fact about an identity, written as a pair: a name and a value. For example: “plan” with the value “premium”, “country” with the value “IN”, “app_version” with the value “5.2.1”, “is_staff” with the value true, or “orders_count” with the value 14.
A trait is one line on a library card. One line says “member since 2022”. Another says “favourite section: science”. Together the lines describe a reader, and the librarian uses them to recommend books.
Parts of a trait
- Key. The name of the fact, such as “plan”. Keys should be consistent and clear.
- Value. The fact itself. It can be text, a whole number, a decimal number or a true-or-false value.
- Owner. The identity the fact belongs to.
Traits versus feature values
New learners sometimes confuse traits with flag values. The difference is simple. A trait describes the user and flows from your application to Flagsmith. A flag value describes what the feature should do and flows from Flagsmith to your application. One is the question’s input. The other is the answer’s output.
| Question | Trait | Flag value |
|---|---|---|
| What does it describe? | A user | A feature |
| Where is it set? | By your app, backend or the dashboard | By people in the Flagsmith dashboard or API |
| Which way does it flow? | App to Flagsmith | Flagsmith to app |
| Example | plan = premium | upload_limit_mb = 100 |
| How often does it change? | When the user changes | When the team decides |
Examples of useful traits
plan
Free, standard or premium. Drives entitlements.
country
A short country code. Drives regional launches and legal rules.
app_version
The version of the app in use. Drives compatibility rules.
is_staff
True for employees. Drives early access.
orders_count
How many orders so far. Drives loyalty offers.
signup_month
Month of joining. Drives cohort tests.
Traits are stored and visible to people who can view identities. Do not store passwords, health details or other sensitive personal data as traits. A harmless label such as “premium” is far safer than a detailed personal profile.
4What Is a Segment?
A segment turns facts into groups. It is the reusable “rule of belonging”.
A plain definition
A segment is a named group of users defined by one or more rules. The rules look at traits and decide whether a user belongs to the group. If the facts match, the user is inside the segment. If not, the user is outside. Nobody puts users into a segment by hand. Membership is worked out automatically, every time it is needed.
Examples
- Premium Users: the trait “plan” is equal to “premium”.
- India Beta: the trait “country” is “IN” and the trait “beta” is true.
- Old App Versions: the trait “app_version” is lower than “5.0.0”.
- Heavy Shoppers: the trait “orders_count” is greater than 10.
- Staff: the trait “is_staff” is true.
A segment is like the rule for entering a members’ lounge at an airport: “holds a gold card or flies business class”. Nobody writes your name on a list. The guard checks your card and ticket each time, and you are in or out depending on the facts.
Why segments are separate from flags
You define a segment once and reuse it across many features. If “Premium Users” appears in twenty flags, and one day the definition changes to include a new plan name, you edit one place. This is the same reason a company keeps one list of departments instead of copying it into every document.
Segments and environments
A segment definition belongs to the project, so every environment sees the same rules. But a segment override is stored per environment. It says: “In this environment, for users in this segment, give this feature this setting.” You can therefore have a segment override for Premium Users in production and none in development.
Because segment rules are shared by all environments of a project, editing a rule changes who belongs to the group everywhere. Treat edits to segments as project-wide actions.
5Trait-Based Segmentation: Putting the Two Together
Traits supply the facts. Segments supply the rules. Flags supply the behaviour. Here is how the three fit.
The simple formula
Think of the whole system as three steps, repeated whenever an app asks for flags:
Know the user
The app tells Flagsmith who the user is, and may send fresh facts about them. These are the traits.
Check the rules
Flagsmith compares the traits against each segment’s rules and works out which segments the user belongs to.
Apply the settings
For each feature, Flagsmith finds the best matching segment override. If none applies, it uses the default setting.
Return the answers
The app receives the on or off state and value of every feature, already personalised for this user.
A tiny example
The upload limit
The feature “upload_limit_mb” has a default value of 25. In production, there is a segment override for the segment “Premium Users” that sets the value to 100. Asha’s identity has the trait plan = premium. When Asha’s app asks for flags, Flagsmith sees that Asha belongs to Premium Users and returns 100. When Ravi, who has plan = free, asks, no override applies and he receives 25.
flowchart LR
APP["App sends identity and traits"] --> FS["Flagsmith"]
FS --> EVAL["Compare traits with segment rules"]
EVAL --> IN{"Inside a segment?"}
IN -- "Yes" --> OV["Use the segment override"]
IN -- "No" --> DEF["Use the default feature state"]
OV --> OUT["Personalised flags returned"]
DEF --> OUT
OUT --> APP2["App shows the right behaviour"]
Why this is better than hard-coding
Without this system, a developer would write rules like “if plan is premium and country is India then show the feature” inside the application. Each change would need a new release, and rules would be scattered across many files. With trait-based segmentation, the code only asks, “Is this feature on for this user?” and all the thinking lives in Flagsmith, where non-developers can adjust it safely.
A hotel does not train every staff member on the details of each guest’s room rights. The front desk checks the booking and gives a key that opens exactly the right doors. Segmentation is the front desk, and the flag answer is the key.
6Where Trait Data Comes From
A segment is only as good as the traits behind it. Let us look at all the ways traits reach Flagsmith.
Source 1: The application, through an SDK
An SDK, short for software development kit, is a small helper library that lets your app talk to Flagsmith. When the app asks for flags for a user, it can include traits in the same request. This is the most common route. It is quick and keeps traits fresh, because the app usually knows the latest facts, such as the app version or the language setting.
Source 2: Your backend
Many facts live in your servers and databases: plan, billing status, account age. A backend service can send these to Flagsmith, either when it asks for flags on behalf of a user or whenever a fact changes, for example when a customer upgrades.
Source 3: The dashboard
People can open an identity in the Flagsmith dashboard and add or edit traits by hand. This is useful for testing and for one-off cases. It is not a sensible way to maintain thousands of values.
Source 4: The API and bulk loads
Flagsmith exposes an API for creating identities and setting traits. Teams use it for bulk loads, nightly synchronisation from a customer database, or changes made by scripts.
Source 5: Computed on the spot
Some traits are not stored for long. The app may work them out at the moment of the request, such as the current time of day or the device type, and send them with that one request. Newer versions of Flagsmith support sending such values without saving them, sometimes called transient traits or transient identities. Check your version for how this works.
| Source | Good for | Watch out for |
|---|---|---|
| App SDK | Device facts, version, language, session facts | Users can tamper with data sent from their own device |
| Backend service | Plan, billing, account facts you trust | Keep it in step when facts change |
| Dashboard | Testing, special cases | Manual work does not scale |
| API or bulk load | Synchronisation, migrations | Mass writes can load the system |
| Computed on the spot | Short-lived facts | Not remembered for next time unless stored |
Anything a client app sends can be altered by a determined user. For facts that grant money-related entitlements, such as plan, send the trait from a trusted backend, and consider turning off the environment option that lets client apps set traits. Check the setting name in your version.
Choose one source of truth
For every trait, decide which system is the boss. If the billing system says a customer is premium, then every other system should copy that fact, never invent it. Two sources of truth for one trait produce two answers, and users see odd behaviour.
7Trait Data Types and Naming
Small details about how a trait is typed and named decide whether a rule works or silently fails.
The common types
- Text. Words and codes, such as “premium” or “IN”.
- Whole numbers. Counts, such as 14 orders.
- Decimal numbers. Amounts or scores, such as 4.5.
- True or false. Yes-or-no facts, such as whether someone is staff.
Why types matter
Imagine a rule says “orders_count is greater than 10”. If one app sends 14 as a number and another sends “14” as text, comparisons may behave differently. Text is compared letter by letter, so the text “9” is larger than the text “10”, because the character 9 comes after the character 1. Flagsmith tries to interpret values sensibly, but you should not rely on that. Pick one type per trait, and always send that type.
In a dictionary, “apple” comes before “banana” because words are sorted by letters. If you sorted house numbers the same way, house “9” would come after house “10”. Numbers must be treated as numbers, or the order goes wrong.
Naming rules that save pain
| Habit | Good example | Poor example |
|---|---|---|
| Consistent style | app_version | AppVersion, appversion, App Version |
| Clear meaning | is_staff | flag1 |
| Same spelling everywhere | country | country, Country, ctry |
| Standard value formats | country = IN | India, india, IND, in |
| Booleans as booleans | is_staff = true | is_staff = “yes” |
Case and spelling traps
A trait named “Plan” and a trait named “plan” are different traits. A value of “Premium” and a value of “premium” may be different values, depending on the operator used. Pick one style, write it down, and make every app follow it.
Keep a small catalogue, a shared page that lists each trait, its meaning, its type, its allowed values and its source of truth. This one page prevents more bugs than any amount of clever testing.
8Writing Segment Rules
Rules are where traits become decisions. Let us learn how to read and write them.
Anatomy of a rule
A segment is made of rules, and each rule contains conditions. A condition has three parts: a property, which is the trait name; an operator, which is the comparison; and a value, which is what to compare against. For example: property “plan”, operator “is equal to”, value “premium”.
Combining conditions
Rules can combine conditions in three ways:
Every condition must match
Like “and”. “Plan is premium and country is IN”.
At least one must match
Like “or”. “Plan is premium or is_staff is true”.
No condition may match
Like “not”. “Not in the blocked-country list”.
You can also nest rules inside rules, so that “ALL of these, and ANY of those” can be expressed. A segment contains one or more top-level rules, and every top-level rule must be satisfied for the user to belong.
Common operators
| Operator | Meaning | Example |
|---|---|---|
| Equals, not equals | Exact comparison | plan equals premium |
| Greater than, less than, and with or equal | Number comparison | orders_count greater than 10 |
| Contains, does not contain | Part of a text | email_domain contains example |
| Matches a pattern (regular expression) | Flexible text matching | app_version matches a pattern |
| Is set, is not set | Whether the trait exists at all | beta is set |
| In a list | Matches any item of a list | country in IN, BR, US |
| Percentage split | A stable share of users | 10 percent of identities |
The exact list of operators, such as list matching or version-aware comparison, has grown over Flagsmith releases. Check what your dashboard and your SDK versions support before relying on any particular operator.
Three small examples in words
Example A: Premium customers in India
Segment “India Premium”. One rule, ALL of: country equals IN, and plan equals premium.
Example B: Staff or beta testers
Segment “Early Access”. One rule, ANY of: is_staff equals true, or beta equals true.
Example C: Everyone except blocked countries
Segment “Open Markets”. One rule, NONE of: country in the list of blocked countries.
9Special Cases: Percentages, Versions and Missing Traits
A few kinds of rules behave differently from the plain comparisons. Knowing them avoids surprises.
Percentage splits
A percentage split rule picks a share of users, such as ten percent, without looking at any particular trait. It is the tool for gradual rollouts: ten percent today, thirty tomorrow, everybody next week. Flagsmith decides membership by turning the user’s identifier into a stable number, so the same user lands on the same side every time. Users do not flicker in and out of the group between visits.
Imagine giving every customer a numbered ticket when they join, and saying “tickets 1 to 10 out of 100 get the new menu”. Each person always has the same ticket, so each person always gets the same menu. When you raise the cut to 30, people with tickets 11 to 30 join, and nobody who was already included drops out.
Raising a percentage safely
Because the share is stable, raising it from ten to thirty keeps the original ten inside, and adds twenty more. This is what makes staged rollouts predictable. Lowering it removes users from the top of the range, which may suddenly take a feature away from some people, so plan communication for that.
Percentage splits combined with traits
A percentage rule can sit next to trait rules in an ALL group. For example, “country equals IN, and ten percent of users”. The result is ten percent of Indian users. This is the standard way to roll out regionally and gradually at once.
Versions
App versions look like numbers but are not: 5.10.0 is newer than 5.9.0, though as text “5.9.0” sorts after “5.10.0”. Comparing versions as plain text goes wrong. Newer Flagsmith versions offer a way to mark a comparison as a version comparison, often by adding a short marker to the value, so that version numbers are ordered correctly. If your version supports it, use it for every rule about app or software versions.
A rule that says “app_version is less than 5.0.0” can behave badly if both sides are treated as text. Test version rules with real examples, such as 4.9.9, 5.0.0 and 5.10.0, before you trust them.
When a trait is missing
What if a user has no value for a trait, such as a brand-new user without a “plan” yet? Most comparison operators treat a missing trait as not matching. A rule “plan equals premium” will not match. A rule using “is not set” will match. A NONE group may match, because none of its conditions are true. Always ask: “What happens to someone who has no value here?” and test that case on purpose.
| Rule | User has plan = premium | User has plan = free | User has no plan trait |
|---|---|---|---|
| plan equals premium | Match | No match | No match |
| plan not equals premium | No match | Match | Depends on version, test it |
| plan is set | Match | Match | No match |
| plan is not set | No match | No match | Match |
Unknown users
Users who have not signed in have no stable identity. You can still serve them flags through the environment’s general settings, or give them a temporary anonymous identifier. Be careful: if the anonymous identifier changes at every visit, percentage rollouts will give them a different answer each time.
10Architecture and Core Components
To trust a system, it helps to know what it is made of. Here are the moving parts behind trait-based segmentation.
The building blocks
Application and SDK
The place where users meet your product. It asks Flagsmith for flags and may send traits.
Backend services
The trusted systems that know the facts: billing, accounts, profiles.
API
The doorway through which apps and people read and change data.
Database
The durable store for features, segments, identities and traits.
Evaluation engine
The part that compares traits with rules and decides the answer.
Read layer and caches
Fast copies near the apps, so flag requests are answered quickly.
flowchart LR
U["User"] --> APP["App with SDK"]
BILL["Billing and Account Systems"] --> BE["Backend Service"]
APP --> API["Flagsmith API"]
BE --> API
API --> ENG["Evaluation Engine"]
ENG --> DB[("Database: features, segments, identities, traits")]
ENG --> CACHE["Read Cache or Edge Layer"]
CACHE --> APP
ADMIN["Team in Dashboard"] --> API
Two kinds of traffic
Flagsmith handles two very different kinds of work. The first is flag reading: apps asking for flags, constantly, from many users. The second is management: people creating segments, editing rules and changing flags. Management happens a few times an hour. Flag reading may happen millions of times a minute. The two paths are designed to stay apart, so a busy dashboard never slows customers.
Where traits are stored
When an app sends traits with an identity, Flagsmith usually saves them against that identity in its database, so that the next visit starts with the same facts. This is called persisted traits. Server programs that use local evaluation may instead keep identities and traits in their own memory. We discuss that choice in a later chapter.
The database is the filing room. The cache is the pile of most-used files on the front desk. The evaluation engine is the clerk who reads a card, checks the rules and says “this customer gets the gold counter”. Customers talk to the front desk, not to the filing room.
11How Evaluation Works Internally
Let us follow a single request from an app, all the way to the personalised answer.
Step by step
The app identifies the user
It sends the environment key, the user’s identifier, and optionally a few traits.
The key is checked
Flagsmith confirms that the key belongs to a real environment.
The identity is found or created
If this identifier is new, Flagsmith creates the record. Otherwise it loads the existing one.
Traits are merged
Traits sent in this request are combined with the stored ones. Where both exist, the newly sent value wins, and may be saved.
Segments are evaluated
For each segment in the project, the engine checks whether the user’s traits satisfy its rules.
Overrides are chosen
For each feature, the engine picks the winning override: a personal override first, then the highest-priority matching segment, then the environment default.
Answers are returned
The list of features with their states and values is sent back to the app.
sequenceDiagram
participant U as User
participant A as App with SDK
participant F as Flagsmith API
participant E as Evaluation Engine
participant D as Database
U->>A: Opens the app
A->>F: Identify user with traits
F->>D: Load identity and stored traits
D-->>F: Identity and traits
F->>E: Merge traits and evaluate segments
E-->>F: Segments matched and winning overrides
F->>D: Save updated traits
F-->>A: Personalised flags
A-->>U: Shows the right behaviour
The order of authority
When several settings could apply to the same feature, Flagsmith picks one using a fixed order. First, an identity override, a special setting for one named user. Second, the highest-priority segment override whose segment matches. Third, the environment default. Understanding this order explains most “why did I get this value?” questions.
Evaluation is repeated, not remembered
Segment membership is worked out every time flags are requested, from the latest traits. It is not stored as a list. This means that when a trait changes, say a customer upgrades to premium, the next request already reflects the new membership. No one needs to move the user between groups.
Because membership is computed from traits, a segment is not a snapshot. It is a live question that is asked again each time.
12Segment Overrides, Priority and Identity Overrides
A segment on its own does nothing. It needs to be attached to a feature through an override.
What an override says
A segment override reads like a sentence: “For this feature, in this environment, for users in this segment, use this state and this value.” You can attach many overrides to one feature, each with its own segment.
Priority
One user can belong to several segments at once. A Premium user in India may match both “Premium Users” and “India Users”. If both have overrides for the same feature, Flagsmith needs a tie-breaker. Overrides are ranked, and the highest-ranked matching one wins. You can reorder the ranking in the dashboard.
flowchart TD
START["Feature requested for a user"] --> Q1{"Identity override exists?"}
Q1 -- "Yes" --> R1["Use the identity override"]
Q1 -- "No" --> Q2{"Matches the top segment override?"}
Q2 -- "Yes" --> R2["Use that segment override"]
Q2 -- "No" --> Q3{"Matches the next segment override?"}
Q3 -- "Yes" --> R3["Use that segment override"]
Q3 -- "No" --> R4["Use the environment default"]
A worked example
| Priority | Segment | upload_limit_mb |
|---|---|---|
| 1 (highest) | Staff | 500 |
| 2 | Premium Users | 100 |
| 3 | India Users | 40 |
| Default | Everyone else | 25 |
A premium customer in India matches Premium Users and India Users. Premium has higher priority, so they receive 100. A staff member who is also premium receives 500. A free user in India receives 40. A free user elsewhere receives 25.
Identity overrides
Sometimes you want a special setting for exactly one person: a customer who is part of a pilot, or an executive who wants an early preview. An identity override gives that one identity its own setting for a feature, and it beats every segment. Use it sparingly, since individual exceptions are hard to track and easy to forget.
Order matters, so review it
A broad segment placed above a narrow one can swallow the narrow one entirely. Put specific segments above general ones, and review the order whenever you add a new override.
A club has several discounts. A founder gets half price, a student gets a quarter off, and everyone else pays full price. If a founder who is also a student walks in, the club must say which discount applies. The ranked list is the club’s answer.
13Step by Step: Creating a Trait-Based Segment
Here is the usual path in the dashboard. Labels may vary a little between versions.
Before you begin
- Decide which fact you will use, and make sure an app or a backend actually sends it.
- Write the segment name and its purpose in one sentence.
- Check the trait catalogue for the exact trait name, type and allowed values.
- Decide which environment you will test in first.
The steps
Open the segments area
In your project, open the segments page and choose to create a new segment.
Name it clearly
Use a name that says what the group is, such as “Premium Users” or “App Older Than 5.0”. Add a short description.
Add a rule
Choose how conditions combine: all, any or none.
Add conditions
For each, enter the trait name, pick the operator and type the value.
Save the segment
It now exists in the project, available to every environment, but affects nothing yet.
Attach it to a feature
Open a feature in the chosen environment, add a segment override, pick the segment and set the state and value.
Test with real examples
Check a user who should match and a user who should not, as well as one with a missing trait.
Checking who matches
The dashboard offers ways to look at identities and their traits, and in many versions it can show which identities a segment currently includes, or which segments an identity belongs to. Use these views while testing. They turn a guess into a fact.
Start with the narrowest useful group, such as staff, and widen step by step. Widening is easy. Taking a feature back from thousands of users is not.
14Sending Traits From Your Application
Rules are useless without data. This chapter explains how traits get from your product into Flagsmith, in plain steps without code.
The moments when traits are sent
- At sign-in. The app tells Flagsmith who the user is and sends the main facts it knows.
- When something changes. The user upgrades, changes country or finishes onboarding, and the app or backend sends the changed fact.
- At app start. Facts like the app version and device type are sent each time, since they may change after an update.
- In the background. A scheduled job copies fresh facts, such as order counts, from your database.
Setting versus reading
SDKs generally offer two different actions. One is “give me the flags for this user, and here are some traits”. The other is “just update this trait”. Choose based on what the screen needs. If the app needs flags anyway, send the traits along with the same request and save a trip.
Removing a trait
To remove a fact that no longer applies, you send the trait with an empty value, which in most versions deletes it. Do this when, for example, a customer cancels a plan. Leaving an old trait lying around means the user may still match old segments.
Keep traits in step with the truth
Update on change
Send the new value when the fact changes. Accurate and quick, but needs hooks in your systems.
Nightly sync
Copy a batch of facts regularly. Simple, but facts can be hours old.
Send with each request
The app sends current facts every time. Always fresh, but relies on the app being honest.
Mix of the above
Trusted facts from the backend, device facts from the app. Common in practice.
Each trait costs storage and a little processing time on every request. Send the handful of facts you really use in rules, not the whole user profile.
Be gentle with writes
If you send the same unchanged traits with every single request, you create many needless writes. Where your SDK allows it, send traits only when they change, or use the option to send short-lived facts without saving them.
15Remote and Local Evaluation With Traits
Flagsmith can decide the answer in two places. Each has strengths and different rules about traits.
Remote evaluation
In remote evaluation, the app asks Flagsmith for the flags of a user, and Flagsmith works out the answer on its servers. Traits are sent with the request or read from storage. This is the default for client-side apps, and it keeps your rules and other users’ data away from the device.
Local evaluation
In local evaluation, a trusted server-side program downloads the whole environment once, including features, segments and overrides, and keeps it in memory. When it needs an answer for a user, it works it out itself, using the traits you supply at that moment. It refreshes the downloaded copy from time to time. This reduces network chatter and can be faster under heavy load.
| Question | Remote evaluation | Local evaluation |
|---|---|---|
| Who works out the answer? | Flagsmith servers | Your own server program |
| Where do traits come from? | Sent with request or stored by Flagsmith | Supplied by your program at call time |
| Are traits saved? | Usually yes | Usually not, they are used then forgotten |
| Best for | Web and mobile apps | Busy backend services |
| Key used | Client-side environment key | Server-side key, which must stay secret |
| Freshness | Immediate | As fresh as the last refresh |
The catch with local evaluation
With local evaluation, Flagsmith does not hold the user’s traits unless you also send them there. So if you rely on stored traits, you must supply them from your own systems each time, or the rules will see an empty user. Test this early.
Remote evaluation is like phoning the head office for every decision. Local evaluation is like keeping the rulebook on your own desk and checking it yourself. With the rulebook, you also need the customer’s details in front of you, since head office is no longer holding them for you.
Choosing between them
- Browser and mobile apps: remote evaluation, because the server-side key must never be placed in a device.
- Backend with high traffic and trusted data: local evaluation is worth trying.
- Mixed systems: use both, each where it fits.
The key used for local evaluation can read the whole environment’s rules. Keep it in a secrets manager and only on servers you control.
16Data Flow and Lifecycle of a Trait
A trait has a life: it is born, it changes and it eventually goes away. Planning for each stage prevents stale data.
Stage 1: Birth
A fact first appears, for example when a user signs up. The app or backend sends the first value, and Flagsmith stores it against the identity.
Stage 2: Use
Each time flags are requested, the trait is compared with segment rules. Its value decides which segments the user belongs to.
Stage 3: Change
The user’s situation changes. The new value is sent, and the old one is replaced. From the very next request, the new value drives targeting.
Stage 4: Staleness
If nothing updates the trait when reality changes, it becomes stale. A customer who cancelled a year ago may still be marked premium. This is the most common quiet bug in trait systems.
Stage 5: Removal
The fact no longer applies, or the user leaves. The trait is cleared, and in some cases the whole identity is deleted to meet privacy rules.
stateDiagram-v2
[*] --> Created: First value sent
Created --> InUse: Evaluated on each request
InUse --> Updated: Fact changes and new value sent
Updated --> InUse
InUse --> Stale: Reality changed, nothing updated
Stale --> Updated: Sync catches up
InUse --> Removed: Trait cleared
Stale --> Removed: Clean-up
Removed --> [*]
Planning for each stage
| Stage | Question to answer in advance |
|---|---|
| Birth | Which system sends the first value, and when? |
| Use | Which segments rely on it, and who owns them? |
| Change | How fast must a change reach Flagsmith? |
| Staleness | How do we detect and fix out-of-date values? |
| Removal | When is a trait deleted, and who is allowed to? |
Deleting users
Privacy laws in many places give people the right to have their data removed. If identities and traits count as personal data in your setup, you need a way to delete them on request. Plan this early. It is far easier to include deletion in the design than to add it after a request arrives.
17Designing a Clean Trait Schema
A “schema” is just an agreed list of traits and their meanings. A tidy schema keeps a growing company out of trouble.
Start from the questions, not the data
Many teams begin by sending every fact they have, then wonder what to do with it. Do the opposite. List the decisions you want flags to make: who gets early access, which plan unlocks which feature, which regions are ready. Then decide which minimal facts are needed to make each decision.
The catalogue
| Trait | Type | Allowed values | Source of truth | Owner |
|---|---|---|---|---|
| plan | Text | free, standard, premium | Billing system | Billing team |
| country | Text | Two-letter country codes | Account profile | Accounts team |
| app_version | Text, version style | Version numbers | App at start-up | Mobile team |
| is_staff | True or false | true, false | Company directory | IT team |
| orders_count | Whole number | 0 and above | Orders database | Commerce team |
| signup_month | Text | Year and month, like 2026-10 | Account system | Accounts team |
Principles of a good schema
- Few and meaningful. Every trait must be used by at least one rule, or removed.
- Stable names. Renaming a trait means every segment using it must change at once.
- Coarse rather than precise. “age_group” is usually safer and just as useful as an exact birth date.
- Derived, not raw. Send “is_premium” or “plan” instead of raw payment details.
- Documented owners. Every trait has a team that answers questions about it.
Planning change
When you must rename or retype a trait, do it in steps. First send both the old and the new trait. Then update segments to use the new one. Finally stop sending the old one and remove it. Doing it all at once risks a gap where nobody matches any rule.
Large companies keep an internal registry of user attributes used for targeting, with owners and review dates. Facebook has described a long-running gating system that depends on attributes of users, and the lesson is the same everywhere: the discipline around attributes matters as much as the tool.
18Common Use Cases
Trait-based segmentation solves many everyday problems. Here are the most common ones, with plain examples.
Use case 1: Plan-based entitlements
Features follow the plan
A document tool gives free users three exports a month, standard users thirty, and premium users unlimited. One feature, “monthly_export_limit”, has a default of 3 and two segment overrides based on the trait “plan”. When a customer upgrades, the backend updates the trait, and the next request shows the new limit with no release.
Use case 2: Early access for staff and beta users
Staff first, always
Every new feature is first switched on for the segment “Staff”, defined by the trait “is_staff”. Employees use it for a week and report problems. Later the “Beta Testers” segment is added, based on a trait set when users opt in.
Use case 3: Regional launches
One country at a time
A shopping app launches a same-day delivery option in one country first, using the trait “country”. Support and logistics are ready there. Other countries are added one by one, by editing the segment rule to include more country codes.
Use case 4: Compatibility with old versions
Protect people on old apps
A new payment screen needs app version 5.0 or later. A segment “Old App Versions” uses the trait “app_version” to keep the screen off for older apps, which would crash. When almost nobody remains on the old versions, the segment and the rule can be retired.
Use case 5: Cohort tests
New users only
A team wants to test a shorter sign-up flow. They use a trait “signup_month” and a segment of people who joined this month, so that the test is not mixed with long-time users who already know the product.
Use case 6: Loyalty and behaviour
Reward the heavy users
A segment “Heavy Shoppers”, using the trait “orders_count”, unlocks a free-delivery banner. A nightly job updates the count from the orders database.
Use case 7: Gradual rollouts with safety
Ten percent, then more
A segment with a percentage-split rule exposes a new search page to ten percent of users, then thirty, then everyone. Each step comes with a pause to watch error rates.
Use case 8: Customer-specific behaviour in business products
One customer, one setting
In software sold to companies, every user carries a trait such as “company_id”. A segment per large customer allows special limits or pilot features for that customer’s employees only.
Use case 9: Kill switches for part of the audience
Turn off only where it hurts
A bug affects only one browser type. A segment based on a “browser” trait turns the feature off for that browser, while everyone else keeps it. Much safer than switching it off for the whole world.
19Segments, Multivariate Flags and Experiments
Segments pair naturally with experiments. Used well, they help teams learn what works for whom.
Multivariate flags
A multivariate flag has several possible values, split by percentages. A button might be blue for fifty percent of users, green for thirty and orange for twenty. A segment override can change these splits for a certain group. For instance, new customers might see an equal three-way split, while long-time customers always see the blue button.
Why segments help experiments
- Focus. A test about checkout belongs to people who actually reach checkout.
- Fairness. Comparing new customers with long-time customers mixes two different groups. Segments keep comparisons clean.
- Safety. Risky variations can be shown first to staff or to a small group.
- Exclusion. Some groups, such as customers in a sensitive period, can be kept out of tests.
An example
Testing a shorter checkout for new customers
The team defines a segment “New Customers”, where orders_count equals 0. In production, they add an override for the feature “checkout_flow” on that segment, with a multivariate split: half see the old flow, half see the short one. Everyone else keeps the old flow. They compare completion rates only among new customers.
Things to watch
Two experiments at once
Users in two experiments may be influenced by both. Keep important tests apart.
Changing group membership
If a trait changes mid-test, a user may move groups and spoil the comparison.
Groups too small
Tiny segments give noisy results. Make sure the group has enough users.
Recording who saw what
Send the variation shown to your analytics tool, or you cannot judge the result.
Big experimenters such as Google and Netflix have written about careful, group-aware testing. The lesson for small teams is simple: decide the group, the change and the measure before you start, and write them down.
20Privacy and Security
Traits are data about people. Treat them with the same care you give any customer data.
Minimise what you send
The safest data is data you never collect. For every trait, ask: “Which rule needs this?” If none, do not send it. Prefer labels over details: “premium” instead of a payment history; “age_group” instead of a birth date.
Avoid direct personal identifiers
Use an internal customer number, or a one-way scrambled form of an email address, as the identity identifier instead of the raw email or phone number. If a trait or identifier leaks in a log or a screenshot, it should not point straight to a person.
Sensitive categories
Never use traits for sensitive information such as health conditions, religion, political opinions or similar categories, unless you have a clear legal basis and strong controls. Many rules place special limits on these. A simple company rule of “no sensitive categories in Flagsmith” avoids a lot of risk.
Who can see what
- Control who can view identities and traits in the dashboard. Few people need to see them.
- Use environment settings that hide sensitive values where offered.
- Give staff the least access they need for their work.
- Review the access list regularly.
Trust and tampering
Traits sent by a client app can be changed by a clever user. If a trait gives paid features, send it from a trusted backend, and consider disabling client-set traits in that environment. For harmless traits such as the app language, a client is fine.
If a shop lets customers write their own discount level on their loyalty card, some will write “platinum”. The shop keeps the real record behind the counter. Traits that matter must be written by the staff, not by the customer.
Keys
The client-side environment key is designed to be visible in apps and only lets them read flags and set limited facts. The server-side key is powerful and must be secret. Store it in a secrets manager and rotate it from time to time.
Rules and laws
Data protection laws in many countries, such as the European GDPR, India’s data protection law and others, care about how personal data is collected, used, stored and deleted. Talk to your privacy or legal team. Show them the trait catalogue, and tell them where Flagsmith is hosted.
Safe habits
- Few, coarse traits.
- Scrambled identifiers.
- Backend-sent entitlements.
- Limited dashboard access.
- A way to delete identities on request.
Risky habits
- Sending the whole customer profile.
- Raw emails as identifiers.
- Letting clients set plan traits.
- Sensitive categories in traits.
- Everyone has access to identities.
21Performance, Scalability and High Availability
Products with millions of users need targeting that stays fast and stays up. Here is what to think about.
What costs time
For each flag request, Flagsmith must load the identity and its traits, compare them with every segment rule, and choose the override for each feature. A few dozen simple segments are trivial. Hundreds of complicated segments, with many nested rules and heavy text patterns, cost more. Writes also cost: saving traits on each request creates database work.
Ways to keep it fast
Keep rules simple
Prefer equals and list matches over complex patterns where you can.
Retire unused segments
Each unused segment is checked for nothing. Delete what you no longer need.
Send traits only when needed
Avoid saving unchanged values on every request.
Use caches and edge layers
Let fast read layers answer popular requests close to the user.
Use local evaluation for heavy servers
Decide on your own server, and save round trips.
Clean old identities
Remove identities of users long gone, to keep the database lean.
Scale out and stay up
The managed Flagsmith service handles scaling for you, using spread-out read layers. A self-hosted installation can run several copies of the API behind a load balancer, with a primary database that has a standby copy ready to take over. The write path for traits tends to be the busiest part, so give the database plenty of room, and watch it as traffic grows.
If Flagsmith has a bad day
Apps should survive a short outage. Give every flag a safe default value in the code. Where possible, let SDKs keep a recent copy of flags so the app can carry on. Decide in advance what each feature does when it cannot learn the answer: for a risky new feature, “off” is normally safest.
Caches mean that a change to a rule can take a few moments to reach every user. Do not design anything that needs every user to switch at exactly the same instant.
22Monitoring, Debugging and Audit
When a user says “I do not see the feature”, you need a fast way to find out why.
The identity page
The Flagsmith dashboard can show the details of an identity: its traits, the segments it currently belongs to and the feature values it would receive. This is the single most useful debugging view. Open the user’s identity, check the traits, and compare them with the segment rules.
A debugging routine
Confirm the identity
Is the app sending the identifier you expect? A different identifier means a different person to Flagsmith.
Look at the traits
Are the traits present, with the right spelling, type and value?
Check segment membership
Does the user belong to the segment you expect? If not, read the rule slowly.
Check the override and its order
Is there an override for this feature? Is a higher-priority segment winning?
Check the environment
Is the app using the right environment key? A staging key will not see production overrides.
Check freshness
Is the app showing an old cached answer? Restart or wait for the refresh.
The audit log
Flagsmith keeps an audit log that records who changed what and when, including edits to segments and overrides. If a group suddenly behaves differently, check whether somebody edited a rule a few minutes earlier. Because segments are shared across a project, one edit can have wide effects.
Useful numbers to watch
- How many users fall in each important segment, and how that changes over time.
- How many identities have each trait set, to spot missing data.
- How many trait writes happen per minute.
- Error rates in the app after a segment change.
When a segment rule changes, post a short note in your team’s chat or change log. The note should say which rule changed, why, and which features are affected.
23Testing Segments Before They Reach Customers
A segment rule is a small program. Like any program, it needs testing.
Build a test table
For each segment, write down a handful of imaginary users and the answer you expect. Include the normal cases, the edges and the odd ones. Run each through Flagsmith, using test identities in a safe environment, and compare.
| Test user | Traits | Expected for “Premium India” |
|---|---|---|
| Typical match | plan = premium, country = IN | Inside |
| Wrong plan | plan = free, country = IN | Outside |
| Wrong country | plan = premium, country = US | Outside |
| Missing country | plan = premium | Outside |
| Wrong case | plan = Premium, country = IN | Depends on operator, check it |
| Wrong type | plan = 1, country = IN | Outside |
Use staging that looks like production
Test in a staging environment with the same segments and similar traits as production. Use fake users with names that cannot be confused with real people, such as “test-premium-india-01”. Never test by editing real customers’ traits.
Dry runs for rollouts
Before a big launch, go through the full plan in staging: create the segments, add the overrides, change the percentages and check each step with test users. A rehearsal in a safe space finds mistakes cheaply.
After the change
- Check a few real identities in production to confirm they land in the expected segments.
- Watch error graphs and key business numbers for the next hour.
- Have a one-minute undo plan: for example, disable the override.
A theatre runs a dress rehearsal before opening night. Actors wear the costumes and use the props, but the audience is a few friends. A staging test with fake users is a dress rehearsal for a segment.
Most segment bugs hide in edges: missing traits, uppercase letters, versions with two digits, empty strings and unusual number formats. Put each of these in your test table.
24Advantages, Disadvantages and Trade-offs
No design is perfect. Here is an honest look at what trait-based segmentation gives and what it costs.
Advantages
- Targeting changes need no new release.
- Rules live in one place, reusable across features.
- Smaller blast radius for risky changes.
- Entitlements follow business facts like plan.
- Non-developers can adjust groups safely.
- Supports experiments and staged rollouts.
Disadvantages
- Depends on accurate, fresh trait data.
- Many segments become hard to understand.
- Shared segments make edits risky.
- Traits are personal data and need care.
- Extra writes and reads add load.
- Debugging needs the right views and habits.
Rules in Flagsmith versus rules in code
| Question | Rules in code | Rules in segments |
|---|---|---|
| Changing a rule | New release | Edit in dashboard |
| Who can change | Developers | Anyone with permission |
| Visibility | Scattered across files | One list of segments |
| Testing | Automated tests | Test identities and tables |
| Risk of misuse | Lower, review by code review | Higher, needs permission and review habits |
Flexibility versus clarity
The freedom to define any segment is also the freedom to make a mess. Teams that enjoy the freedom without discipline end up with hundreds of overlapping segments that nobody understands. A modest list of well-named, well-owned segments is nearly always better than a huge, clever one.
Central rules versus local needs
Shared segments encourage reuse, but one edit touches every feature that uses it. Some teams prefer a few shared segments for company-wide ideas, such as Staff, and private segments for feature-specific needs, with clear names. Use the style that fits your size.
25Design Patterns and Anti-Patterns
Patterns are habits that other teams have already tested. Anti-patterns are habits that looked clever and then caused pain.
Pattern 1: Staff first
Every new feature goes first to the Staff segment. Employees are forgiving, they know whom to tell, and they find the obvious problems.
Pattern 2: Widening rings
Release in rings: staff, then beta testers, then ten percent, then fifty percent, then everyone. Each ring is one segment or one percentage, and each ring has a pause to watch the numbers.
Pattern 3: Entitlement segments
Create one segment per plan, based on a single trusted trait. Flags attach to these segments for limits and features. The business changes a plan’s rights by editing overrides, not by editing code.
Pattern 4: Compatibility guards
Use an app-version segment to hide features from versions that cannot support them. Pair it with a plan to retire old versions.
Pattern 5: Derived traits
Compute a simple label in your backend, such as “customer_tier”, from many raw facts, and send only the label. Rules stay short, and the complex logic lives in a system built for it.
flowchart LR
S["Staff"] --> B["Beta Testers"]
B --> P10["10 percent of users"]
P10 --> P50["50 percent of users"]
P50 --> ALL["Everyone"]
S -.-> W1["Watch and fix"]
B -.-> W2["Watch and fix"]
P10 -.-> W3["Watch and fix"]
P50 -.-> W4["Watch and fix"]
What it looks like
Dozens of segments with names like “Test2”, “NewSegment” and “Temp Users”.
Why it hurts
Nobody knows what they mean. Features depend on them, and nobody dares to delete them.
Better approach
Clear names, owners and a short description. Review and retire segments every quarter.
What it looks like
The whole customer profile is sent as traits, just in case.
Why it hurts
More personal data, more storage, more risk, and no rule uses most of it.
Better approach
Send only the facts that rules need.
What it looks like
A free-text trait like “notes” or a trait whose spelling differs between apps.
Why it hurts
Rules never match consistently, and bugs are hard to explain.
Better approach
Fixed values from a catalogue, with checks in the sending code.
What it looks like
Client apps set the “plan” trait that unlocks paid features.
Why it hurts
A user can change it and unlock features for free.
Better approach
Set entitlement traits from a trusted backend and restrict client-set traits.
What it looks like
Many individual identity overrides for special people.
Why it hurts
Exceptions pile up, nobody knows why each exists, and they survive long after the reason is gone.
Better approach
Create a named segment for the group, with a clear reason and an end date.
26Best Practices, Common Mistakes and Troubleshooting
Experienced teams build a few simple habits. Beginners tend to make the same few slips.
Best practices
Keep a trait catalogue
Names, types, allowed values, source and owner in one page.
Choose one source of truth per trait
One system owns each fact. Others copy it.
Name segments by meaning
“Premium Users” beats “Segment 7”.
Put specific segments above general ones
Priority order should follow common sense.
Test edge cases
Missing traits, wrong case, wrong type and odd versions.
Roll out in rings
Staff, beta, small percentage, then everyone.
Protect personal data
Few traits, coarse values, scrambled identifiers.
Review every quarter
Delete unused segments and traits. Check owners and order.
Common mistakes
Typo in the trait name
“contry” never matches “country”. The rule silently matches nobody.
Number sent as text
Comparisons give strange results.
Forgotten missing case
New users without the trait behave unexpectedly.
Wrong environment key
Tests run against staging while you edit production.
Editing a shared segment casually
Every feature using it changes at once.
Stale traits
People keep old plan or country values for months.
Troubleshooting guide
| Symptom | Likely cause | What to do |
|---|---|---|
| User is not in the expected segment | Trait missing, misspelled or wrong type | Open the identity, compare each condition with the traits |
| User gets the wrong value | A higher-priority override wins | Check override order and identity overrides |
| Change not visible yet | Cache or SDK refresh delay | Wait a few moments, refresh the app |
| Rule works in staging, not production | Different traits or overrides per environment | Compare both environments |
| Percentage rollout flips users | Identifier changes between visits | Use a stable identifier |
| Local evaluation ignores stored traits | Traits must be supplied at call time | Pass the traits from your own systems |
| Too many writes | Traits sent unchanged on every request | Send on change, or use short-lived traits |
27Deployment and Cloud: Hosted and Self-Hosted Flagsmith
Where Flagsmith runs changes a few practical details of trait handling.
The hosted service
In the hosted service, Flagsmith runs everything. Scaling, upgrades and read layers close to your users are taken care of. Limits on identities, traits or segments may depend on your plan, so check them before designing a large system.
Self-hosting
Because Flagsmith is open source, a team can run it on its own servers or cloud account. A typical layout has several copies of the API behind a load balancer, a main database with a standby copy, a cache and background workers. Teams choose this path when they must keep data in their own network, or when they want complete control.
flowchart LR
APPS["Apps and Servers using SDKs"] --> LB["Load Balancer"]
LB --> API1["Flagsmith API Copy 1"]
LB --> API2["Flagsmith API Copy 2"]
API1 --> DB[("Primary Database: identities and traits")]
API2 --> DB
DB --> STBY[("Standby Database")]
API1 --> CACHE["Cache Layer"]
API2 --> CACHE
TEAM["Team in Dashboard"] --> LB
API1 --> WORK["Background Workers"]
What matters for traits when self-hosting
- Database room. Traits are many small writes. Make sure the database has headroom, and watch its load as users grow.
- Retention. Decide how long identities are kept, and set up clean-up of old ones.
- Backups. Identities and traits are real data. Back them up, and practise restoring.
- Privacy. You are now the data host. Control access, encrypt data in transit and at rest, and record who can see what.
- Upgrades. After an upgrade, retest a few segment rules, especially those that use newer operators.
The hosted service is eating at a restaurant. Self-hosting is cooking at home. Same meal, but at home you are the one who buys the ingredients, keeps the fridge cold and cleans the kitchen.
Regions and data location
Some companies must keep personal data in certain countries. Where Flagsmith runs, and where its database lives, then matters. Ask Flagsmith about the regions of the hosted service, or choose a self-hosted install in the right location. This is a good reason to keep traits minimal.
Cost thinking
The software cost is mainly the plan tier. Indirect costs include database size, the effort to maintain traits and the time people spend managing segments. Tidy habits keep all three low.
28Governance, Ownership and Teamwork
As more teams use Flagsmith, habits matter as much as features. This chapter covers the human side.
Who owns a segment?
Every segment should have an owner, a person or team, and a one-line purpose. Without an owner, nobody knows if a segment can be changed or deleted. Write the owner in the description, and review the list each quarter.
Who owns a trait?
Every trait has two owners: the team whose system is the source of truth, and the teams whose segments depend on it. Changes to a trait’s meaning must be announced to both.
Permissions
Flagsmith lets administrators control who can view and edit things at several levels: organisation, project and environment. Common sense suggests that many people may read segments, fewer may edit them, and very few may edit segments that affect production for large groups. Remember that editing a segment rule changes it for every environment in the project.
| Role | Segments | Overrides in production | Identities and traits |
|---|---|---|---|
| Engineers | View, propose | Create with review | View test identities |
| Product managers | View | Propose | No access |
| Segment owners | Edit own segments | Edit with review | View for debugging |
| Support staff | View | No access | View single identities when needed |
| Administrators | Settings only | Rarely edit | Limited, logged |
Review for risky changes
Some plans of Flagsmith offer an approval workflow, sometimes called change requests, where a second person must approve changes to a protected environment before they go live. Use it for production overrides that affect many users. Edits to shared segment definitions are especially worth a second pair of eyes.
A short change note
Whenever you edit a segment or an override, write a short note: what changed, why, who is affected, how to undo. A one-line habit like this makes the audit log and team memory far more useful.
Retiring segments and traits
Spring clean every quarter
Once a quarter, list all segments and all traits. For each, ask: Is it used by any feature? Does it still mean what its name says? Who owns it? Anything unused is deleted. Anything unclear is fixed or renamed. This simple chore keeps targeting understandable.
Teaching newcomers
New teammates should learn in their first week: the trait catalogue, the list of main segments, how priority works, how to debug an identity and who to ask. A one-page guide in plain words, with real examples from your project, is worth more than a long manual.
29A Complete Walkthrough: A Tiered Upload Limit and a Staged Launch
Let us follow a made-up product, “Acme Docs”, through a full project to see how every idea in this guide fits together.
The situation
Acme Docs is a document tool with two million monthly users. It has three plans: free, standard and premium. The team wants to give each plan a different upload limit, and also to launch a new “smart search” page carefully. They use one Flagsmith project with Development, Staging and Production.
Stage 1: Decide the questions
The team writes down the decisions they want flags to make: What upload limit does this user get? Should this user see smart search? From this, they decide which facts are needed: the plan, whether the user is staff, the app version and the country.
Stage 2: Build the trait catalogue
They create a one-page catalogue with four traits: plan (text, from billing), is_staff (true or false, from the company directory), app_version (version style, from the app at start-up) and country (two-letter code, from the account profile). Each has an owner, and the billing team is the owner of plan.
Stage 3: Send the traits
The backend sends plan and is_staff whenever they change, and also at sign-in. The app sends app_version at each launch. The environment option that lets client apps set traits is turned off in production, so that users cannot change their own plan.
Stage 4: Define the segments
| Segment | Rule |
|---|---|
| Staff | is_staff equals true |
| Premium Users | plan equals premium |
| Standard Users | plan equals standard |
| Smart Search Ready | app_version at least 5.0.0, version style |
| Smart Search Ring 1 | ALL of: Smart Search Ready, and ten percent of users |
Stage 5: Attach overrides
The feature “upload_limit_mb” has a default of 25, an override of 100 for Standard Users, 500 for Premium Users and 1000 for Staff, ordered with Staff at the top. The feature “smart_search” is off by default. In production, an override turns it on for Staff first.
flowchart LR
A["Decide questions"] --> B["Write trait catalogue"]
B --> C["Send traits from billing and app"]
C --> D["Define segments"]
D --> E["Add overrides in Staging"]
E --> F["Test with fake users"]
F --> G["Copy overrides to Production for Staff"]
G --> H["Widen to 10 percent, then 50, then all"]
H --> I["Review and clean up"]
Stage 6: Test
In Staging, the team creates ten fake users: free, standard and premium; staff and non-staff; app versions 4.9.9, 5.0.0 and 5.10.0; and one with no plan trait. They check each result against a table of expected answers. They discover that the rule for versions was matching 5.10.0 as older than 5.9.0 because of text comparison. They switch the rule to the version-aware style and retest.
Stage 7: Roll out
In Production, smart search is first on for Staff for three days. Then for ten percent of users who are on a ready app version. The team watches error rates and search success. Everything stays calm. They raise the percentage to fifty and then to everyone over the next week, with a short note in the change log at each step.
Stage 8: Learn and tidy
After the launch, they delete the ring segments and keep the plan segments. They write down lessons: send traits from the backend, test versions, and never skip the missing-trait test. They add these to the team’s checklist.
Worked well
- One catalogue, with owners and a single source of truth.
- Plan-based limits changed without any release.
- The version bug was found in staging.
- The ring rollout was calm and well recorded.
Could be better
- The app first sent the version with a stray letter, causing mismatches.
- One older app never sent the version at all.
- Nobody had a clear owner for the country trait at first.
Context
Acme Docs needs plan-based limits and careful feature launches without new releases.
Decision
Entitlement traits are sent only from trusted backends. Segments are based on a small catalogue of named, owned traits. New features go out in rings, beginning with staff.
Consequences
Launch preparation needs more planning, but incidents during launches fall. The team must keep the catalogue current and review segments every quarter.
30Advanced Topics: Nested Rules, Patterns and Trait Hygiene
Once the basics feel comfortable, a few deeper ideas decide how well your targeting ages as the product grows.
Nested rules
A segment can contain rules inside rules. The top level says how the main groups combine, and each inner group says how its own conditions combine. This lets you express sentences such as “country is India or Brazil, and plan is premium or standard, and the user is not staff”. Written out, that is three groups: ANY of two countries, ANY of two plans, and NONE of the staff condition, all required together.
Nested rules are powerful but hard to read. Keep the nesting shallow. If a rule needs more than two levels, ask whether a derived trait, such as “launch_group”, computed in your backend, would say the same thing in one line.
A long sentence with many brackets is hard to follow, however correct it is. A short sentence that says the same thing is easy to check and easy to trust. Derived traits turn long sentences into short ones.
Pattern matching with care
Flexible text patterns, often called regular expressions, can match many forms of a value at once. They are also easy to get wrong, slow when complicated, and hard for colleagues to read. Use them only when simple equals or list matching cannot do the job, and always test them against both matching and non-matching examples.
Segments that depend on other segments
Some teams build segments that mirror other segments, such as “Premium Users in India” copied from “Premium Users” with one extra condition. Copies drift apart. When the definition of premium changes, one copy is updated and the other forgotten. Prefer one clear segment per idea, and combine ideas using override order or derived traits instead of copying rules.
Trait drift
Trait drift is the slow growth of differences between what a trait says and what is true. A customer changes country, but the old value stays. A plan is cancelled, but the trait still says premium. Drift quietly gives people the wrong features. Fight it with three habits:
- Update on change. Wire the source system so that every change sends the new value.
- Reconcile regularly. Once a night or week, compare a sample of identities with the source system and repair differences.
- Measure it. Track how many identities disagree with the source. A rising number is a warning.
Identity hygiene
Identities pile up. Every visitor who ever opened your app may have left an identity behind. Many are never seen again. Decide how long unused identities should live, and remove old ones, for both cost and privacy. If your anonymous visitors get a new identifier every visit, you may be creating a new identity for each of them, which fills the database with throwaway records. Prefer a stable anonymous identifier, or use short-lived traits that are not saved.
Versioning your segments
Treat a major change to a segment like a change to an interface. Create a new segment with the new rule, attach it to features beside the old one, check the effect, and then remove the old one. This avoids the surprise of changing a rule that many features quietly depend on.
flowchart LR
OLD["Old segment in use"] --> NEW["Create new segment with improved rule"]
NEW --> ATT["Attach new segment to features beside the old one"]
ATT --> CMP["Compare results with test users"]
CMP --> SW["Switch overrides to the new segment"]
SW --> DEL["Delete the old segment"]
A worked example: cleaning up a messy project
From sixty segments to twelve
A growing team inherits a project with sixty segments. Some are named after people who left. Several look identical. A few refer to a trait called “Country” while others use “country”. The team starts by exporting the list and marking each segment as used, unused or unknown. Unused ones are deleted in a quiet week, after a final check of the audit log. Duplicates are merged: features that used the copy are re-pointed to the surviving segment, one at a time, with test users confirming each step. The two spellings of the country trait are fixed by sending both for a month, updating every rule, and then stopping the old one. At the end, twelve well-named segments remain, each with an owner, and the trait catalogue finally matches reality. Support staff notice that questions about “why did this user see that?” fall sharply, because every answer is now easy to find.
Questions to ask yourself once a year
- Do our traits still describe the decisions we need to make?
- Which segments have not been used in the last six months?
- How many identities disagree with their source of truth?
- Would we be comfortable showing our trait catalogue to a privacy reviewer tomorrow?
- Could a new teammate debug a wrong flag value in ten minutes?
If you can explain every segment to a colleague in one sentence, your targeting is healthy. If you need a diagram and ten minutes, simplify it.
31Real-World and Industry Examples
Targeting features by user attributes is a long-standing idea. The descriptions below reflect what these companies have discussed publicly, as patterns, not details of private systems.
Facebook: gates based on user attributes
Facebook has described an internal gating system that decides who sees a new feature using attributes of users, such as whether they are employees, which country they are in and what share of users should be included. New features commonly reach staff first, then small groups, and then larger ones. That is the same ring idea described in this guide.
Netflix: careful, group-aware change
Netflix has discussed testing changes on small slices of its audience before broad release, and comparing the groups with measurements. Group-based testing needs clear, stable groups and good records of who saw what, which is exactly what traits and segments provide.
Google: experiments and launch controls
Google has written about running many controlled experiments and about launch processes that expand a change step by step. Targeting by user attributes, region and device type is a normal part of those approaches.
Uber and similar services: place-based rules
Ride and delivery services operate in many cities, each with different rules and readiness. A trait for the city or region lets a feature be switched on city by city, matching local support and law.
Spotify and subscription services: plan-based features
Subscription products give different features and limits to free and paid users. Driving those differences from a single “plan” fact, rather than from scattered code, is a common design that trait-based segmentation supports.
Software for businesses: customer-specific behaviour
Companies that sell to other companies often turn on pilot features for a single customer. A company trait lets a segment target only that customer’s employees, without creating a separate version of the product.
None of these companies treats targeting as an end in itself. They use it to make change safer and more learnable: first for the people who can handle problems, then for more and more users.
32Reusable Checklists
Experienced pilots do not trust memory for routine steps, and neither should you. Copy these into your team wiki.
Before you add a trait
- Name the rule or decision that needs it. No rule, no trait.
- Choose a clear name, a type and allowed values.
- Choose one source of truth and one owner.
- Check whether it is personal data, and whether you may use it.
- Decide how and when it will be updated and removed.
- Add it to the catalogue.
Before you create a segment
- Write the name, the purpose and the owner.
- Check that every trait in the rule exists with the right type.
- Think about users with missing traits.
- Think about the order among other segments.
- Prepare a test table with expected answers.
Before you attach an override in production
- Test with fake users in staging.
- Check the order of overrides for this feature.
- Decide the starting group and how it will widen.
- Write the undo step.
- Tell the people who need to know.
After a change
- Open a few real identities and check their segments.
- Watch error and business graphs for the next hour.
- Record what changed in the change log.
Every quarter
- List all segments and traits. Delete unused ones.
- Check owners and descriptions.
- Review who can edit segments and see identities.
- Look for stale traits.
- Run a test table for the main segments.
A tidy workshop has a hook and a label for every tool. These checklists are the hooks and labels for your targeting workshop.
33Plain-English Glossary
A short reference for the words used in this guide.
Feature flag
A switch outside the code that turns a behaviour on or off.
Remote configuration
A value, such as a number or text, that an app reads from Flagsmith.
Environment
A separate set of flag settings for one stage, such as production.
Identity
A record standing for one user, with an identifier.
Trait
One named fact about an identity, such as plan or country.
Segment
A named group defined by rules over traits.
Rule and condition
A rule combines conditions. A condition is property, operator and value.
Operator
The comparison used in a condition, such as equals or greater than.
Segment override
A different setting of a feature for a segment in one environment.
Identity override
A special setting of a feature for one specific identity.
Priority
The order that decides which matching override wins.
Percentage split
A stable share of users chosen by a hashed identifier.
Multivariate flag
A flag with several values split by percentages.
SDK
A software development kit: a helper library for talking to Flagsmith.
Remote evaluation
Flagsmith works out the answers and sends them to the app.
Local evaluation
A trusted server downloads the rules and decides by itself.
Transient trait
A fact used for one request and not saved.
Cohort
A group of users who share a starting point, such as the month they joined.
Audit log
The record of who changed what and when.
Source of truth
The one system that is the boss of a fact.
34Frequently Asked Questions
Quick answers to the questions that come up most often.
35Summary and Key Takeaways
Let us pull the whole story together in a few lines you can remember.
Key Takeaways
- Traits are facts, segments are rules. A trait describes one user. A segment turns traits into a named group, worked out automatically each time.
- Overrides attach groups to features. The winner is an identity override first, then the highest-priority segment, then the default.
- Data quality decides everything. Use clear names, steady types, one source of truth per trait and fresh values.
- Test the edges. Missing traits, wrong case, wrong type and versions like 5.10.0 are where bugs hide.
- Roll out in rings. Staff first, then beta, then a small percentage, then everyone, watching the numbers at each step.
- Protect personal data. Send few, coarse traits, use scrambled identifiers, and set entitlement traits from trusted backends.
- Keep it tidy. Own every segment and trait, review them each quarter and verify plan and version details in the Flagsmith documentation.