Remote Config Values in Flagsmith
How to change numbers, text, and settings in a live application without a new release: what a remote config value is, how Flagsmith stores and targets it, how apps read it safely, and how to run it in production without surprises.
Every program is full of small decisions that were once typed straight into the code: how many items to show on a page, how long to wait before giving up on a request, what message to display during maintenance, which colour a button should be this month. These little numbers and words are called settings. For years, changing one meant editing the code, testing it, building a new version, and releasing it. That is a lot of work to change a single number from twenty to thirty.
Flagsmith offers a better way. It lets you keep these settings outside your code, change them from a dashboard, and have your running applications pick up the new value on their own. This ability is called remote config, and the settings it manages are called remote config values. In this guide you will learn what they are, how they are stored and targeted, how applications read them safely, and how to avoid the mistakes that turn a handy tool into a source of outages.
1The Problem: Settings Buried in Code
Before meeting the tool, let us feel the pain it removes.
Constants that never stay constant
Programmers call a fixed number written into the code a constant. But many so-called constants are not truly fixed. The number of search results per page, the maximum size of an upload, the time to wait for a payment provider, the text of a banner, and the discount shown on a sale all need to change as the business learns. Each change, if buried in code, needs a new release.
The cost of a release
A release is not free. Someone must make the change, review it, run tests, build the program, deploy it, and watch it. For mobile apps, the cost is higher still: the new version must pass an app store review and then wait for users to update, which can take days or weeks. For something as small as a wording change, the effort is out of all proportion.
Why speed matters in a crisis
Imagine a payment provider starts responding slowly during a busy evening. If the wait time and retry count are fixed in code, the fix is a full release in the middle of an incident. If they are remote config values, an engineer changes two numbers in a dashboard and the problem eases within a minute or two. When things go wrong, that difference is priceless.
Think of a thermostat on the wall versus a heater wired straight to full power. With the wired heater, changing the temperature means calling an electrician to rebuild the wiring. With a thermostat, anyone can turn a dial and the room adjusts. Remote config puts a dial on your software’s settings, so you do not need to rewire anything.
2What a Remote Config Value Is
A flag answers yes or no. A remote config value answers “how much?” or “which one?” or “what should it say?”.
The definition
A remote config value is a piece of data, such as a number, a word, a sentence, or a small block of settings, that is stored in Flagsmith and read by your application while it runs. Because it lives outside the code, you can change it without changing or redeploying the application.
One object with two parts
In Flagsmith, flags and remote config are not two separate things. Both are a feature. Every feature has an on/off state, and may also carry a value. A pure on/off switch simply has no value. A pure setting, such as a page size, may be thought of as a feature whose main purpose is its value. Many features use both: the state says whether a behaviour is active, and the value says how it should behave.
An example
Suppose you have a feature called “search-results-per-page”. Its value is twenty in Production and fifty in Staging. Your search code asks Flagsmith for the value and shows that many results. Tomorrow the product team wants thirty. They open the dashboard, change the value in Production to thirty, and within moments your servers start returning thirty results. No code changed.
flowchart LR
DASH["Dashboard: change value to 30"] --> FS["Flagsmith stores the new value"]
FS --> SDK["Application SDK fetches or refreshes"]
SDK --> APP["Application uses 30 for the next request"]
A restaurant has a chalkboard menu outside. The kitchen’s recipes stay the same, but the chef can rub out “soup of the day: tomato” and write “soup of the day: mushroom” whenever he likes. Passers-by see the new board straight away. A remote config value is the chalkboard: the content changes while the building stays untouched.
When deciding what to call something, ask “is the answer yes or no, or is it a quantity or a text?” Yes or no means a plain flag. Anything else means a value, and you can attach it to a feature whenever you need it.
3Flag or Value? Choosing the Right Tool
Both live in the same place, but they solve different problems.
The simple rule
Use a flag when your code needs to decide whether to do something. Use a value when your code needs to know how much, how long, which one, or what text. Many features use both together.
| Question your code asks | Best tool | Example |
|---|---|---|
| Should this new screen appear? | Flag | new-checkout is on or off |
| How many items per page? | Value | page-size is thirty |
| How long should we wait for the payment provider? | Value | payment-timeout-seconds is eight |
| What does the maintenance banner say? | Value | banner-text holds a sentence |
| Is the recommendation row allowed to run, and with how many items? | Both | State is on, value is ten |
| Which of three button colours should this user see? | Multivariate value | button-colour with three options |
Why not use only values?
A value of zero or an empty text can mimic “off”, but this creates confusion. Is zero a real setting or a switch? A clear on/off state avoids that ambiguity. Using both, state for whether and value for how, keeps your intent obvious.
Why not use only flags?
You could create ten flags called “page-size-10”, “page-size-20”, and so on, but this is clumsy and hard to maintain. A single value is simpler and far easier to change.
Answers “whether”
A switch that shows, hides, or enables behaviour.
Answers “how” or “what”
A setting that tunes, labels, or configures behaviour.
Whether and how
The state turns something on, and the value shapes it.
Which one
A multivariate value picks one choice from several.
A light fitting has a switch and a dimmer. The switch decides whether the light is on. The dimmer decides how bright it is. You would not try to do both jobs with one control. In the same way, the feature state is the switch and the value is the dimmer.
4The Anatomy of a Feature with a Value
To use values well, learn the parts that surround them.
Where features live
Flagsmith organises everything in layers. An organisation holds your team. A project represents one product or application and owns the list of features. An environment, such as Development, Staging, or Production, holds the actual state and value of each feature. A feature is defined once for the project, but each environment keeps its own state and its own value for it.
The parts of a feature
- Name: the label your code uses to ask for it. It should be clear and permanent.
- Description: a human explanation of what the feature does and what the value means, including its unit and allowed range.
- State: on or off in each environment.
- Value: the data held, which can differ per environment.
- Tags: labels for grouping, such as the owning team or the type of setting.
- Overrides: special values for particular segments or individual users.
- Variations: several weighted values for multivariate features.
flowchart TD
P["Project"] --> F["Feature: search-results-per-page"]
F --> D["Description and tags"]
F --> E1["Development: on, value 50"]
F --> E2["Staging: on, value 25"]
F --> E3["Production: on, value 20"]
E3 --> S1["Segment override: beta users, value 30"]
E3 --> I1["Identity override: one customer, value 40"]
The description is part of the design
A value without a description is a riddle. Someone will see “thirty” in the dashboard and wonder whether it means seconds, items, or percent. Write down what the number means, its unit, and the safe range. This one habit prevents a great many mistakes.
A control panel in a factory has dials, and each dial has a printed label saying what it controls, the unit, and the safe range. A dial with no label is dangerous. Treat every remote config value like a labelled dial.
5Types of Values: Text, Numbers, Booleans, and Structured Data
What kind of thing can a value hold, and how should your code treat each?
The basic types
Flagsmith values commonly come in a few basic types. A string is text, such as a sentence or a code name. An integer is a whole number, such as a count or a number of seconds. A boolean is true or false. Depending on your SDK, the value you receive may already have the right type, or may arrive as text that your code must convert. Check how your SDK behaves, because this is a common source of surprise.
Structured values
Sometimes one setting is not enough, and a group of related settings makes sense, such as a timeout, a retry count, and a back-off factor together. Teams often store a small block of structured text, in a format such as JSON, as the value, and have their application read it into separate settings. This is flexible, but it comes with extra risks, which we cover in a later chapter.
| Type | Good for | Careful about |
|---|---|---|
| String | Messages, labels, names, links, mode names | Spelling, case, language, very long text |
| Integer | Counts, sizes, seconds, percentages | Negative numbers, zero, huge numbers, units |
| Boolean | Simple options inside a value | Sent as text such as “true” in some paths |
| Structured text | Groups of related settings | Size, shape changes, invalid text, versions |
Always convert and check
Whatever the type, the receiving code should treat the value as untrusted input. It should convert it to the type it needs, check that it is within a sensible range, and fall back to a safe default if it is not. A person typing into a dashboard can make a typing mistake as easily as anyone, and an extra zero can turn a ten-second timeout into a hundred.
Everyday use case: a typo in a number
An engineer means to set a request timeout to eight seconds but types eighty. Because the application checks that the timeout is between one and thirty seconds, it ignores the bad value, logs a warning, and keeps using the last good one. The mistake is caught by the code and fixed in the dashboard, with no customer affected.
There is a limit to how large a value can be. Treat values as small pieces of configuration, not as a place to store documents or data sets. Check the current documentation for the exact limit on your plan and version.
6Environments: Different Values for Different Stages
The same setting often needs different values in testing and in production.
Why values differ by environment
A development environment may want very long timeouts so engineers can debug. Staging may want results that mimic production but on small data. Production wants tuned, safe values. Because each environment stores its own value for each feature, you can set all of these independently, and a change in one never affects the others.
Safe experimentation
This separation lets developers try values freely. A developer can raise a limit in Development to see how the code behaves, with no risk to customers. When the team is happy, someone sets the agreed value in Production deliberately.
Keeping environments aligned
The danger is drift. Over time, environments may end up with values that nobody remembers choosing, so that Staging no longer resembles Production and tests give false comfort. Review values across environments regularly, and record the reason when they are meant to be different.
| Feature | Development | Staging | Production | Why they differ |
|---|---|---|---|---|
| payment-timeout-seconds | 30 | 10 | 8 | Developers need time to debug |
| search-results-per-page | 50 | 25 | 20 | Smaller test data in lower environments |
| banner-text | Test message | Draft message | Live message | Content is reviewed before going live |
A flight simulator has the same cockpit controls as a real aircraft, but the wind and fuel settings are changed by the instructor to practise. Nobody is in danger when the instructor turns the wind to storm force. Development and Staging are your simulators, and Production is the real sky.
Use separate environment keys for each environment, and load the right one from configuration. A test app pointed at the Production key is a classic way to change a live value by accident.
7Segment Overrides: Different Values for Different Groups
A value does not have to be the same for everyone, even within one environment.
Segments in short
A segment is a saved group of users defined by rules over their traits, which are facts about them such as plan, country, or app version. A segment override gives a feature a different state or value for members of that segment.
Values for groups
This is where remote config becomes powerful. You can say “the upload limit is ten megabytes for everyone, but fifty megabytes for the enterprise plan.” Or “the banner says one thing in India and another in Germany.” Or “the timeout is eight seconds, but twelve seconds for users on slow networks.” One feature, one place to manage, many values depending on who is asking.
Priority matters
Because a person can belong to several segments, overrides are checked in a priority order and the first match wins. If a staff member is also on the enterprise plan, which value should they get? You decide by arranging the order, putting the more important or more specific rule first.
The app sends who the user is
An identifier and a few traits, such as plan and country.
Flagsmith checks the segments
Each segment’s rules are tested against the traits, in priority order.
The first matching override gives its value
If nothing matches, the environment’s normal value is used.
The app uses the value it received
The same code runs for everyone, with different numbers.
Everyday use case: plan-based limits
A file-sharing product keeps one feature called “max-upload-mb”. The environment default is ten. A segment for the “pro” plan overrides it to fifty, and a segment for “enterprise” overrides it to two hundred. When a customer upgrades, their plan trait changes and the new limit applies on their next request. Product teams adjust limits in the dashboard, with no engineering effort.
A theme park has one rule sheet with a base rule: “children under 120 centimetres may not ride”. Special passes then adjust it: “with an adult, allowed on the small rides”. One sheet, one set of rules, with exceptions attached to groups. Segment overrides give your values the same layered structure.
8Identity Overrides and Traits: Values for One Person
Sometimes the right group is a group of one.
Identities and traits
An identity is a unique ID for one user, device, or account. A trait is a fact about that identity. The application sends them together when it asks for values, so Flagsmith can tailor its answer.
Identity overrides
An identity override pins a feature to a particular state or value for exactly one identity. This beats every segment rule, because it is the most specific kind of rule there is. Support teams use it to help one customer: “give this customer a higher export limit while we investigate their problem.” Engineers use it to test a value on their own account in Production before changing it for anyone else.
Handle with care
Personal overrides are easy to create and easy to forget. Months later, nobody remembers why one customer has a special limit, and it may no longer be right. Record the reason for each, add a review date, and include identity overrides in your regular clean-up.
| Level | Applies to | Typical use |
|---|---|---|
| Identity override | One person or account | Support exceptions, personal testing |
| Segment override | A group of people | Plans, regions, beta programmes |
| Environment value | Everyone in the environment | The normal setting |
Test a new value on your own identity first. Create an identity override for yourself in Production, check that the application behaves well, and only then widen the audience. It costs a minute and prevents embarrassment.
A hotel has standard checkout at noon. A group booking may get a later checkout by agreement, and the manager may write a personal note on one guest’s record saying “late checkout until four”. The personal note wins over the group agreement, which wins over the standard rule.
9Multivariate Values: Several Options with Weights
When you want to hand out different values to different users in controlled shares, you use a multivariate feature.
What multivariate means
A multivariate feature has several possible values, called options or variations, and each option has a weight, which is the percentage of users who should receive it. For example, a button label could have three options: “Buy now”, “Add to basket”, and “Get it today”, each given a third of the audience.
Stable assignment
Flagsmith assigns each identity to an option using a repeatable calculation based on the identity and the feature. This means the same person receives the same option every time they return, rather than seeing “Buy now” in the morning and “Get it today” in the afternoon. It also means that no list of “who got what” needs to be stored.
Control and variations
The feature’s own value acts as the standard, or control. The other options are variations that take a share of users from the control. Setting all variation weights to zero means everyone sees the control. This makes it easy to turn an experiment off without deleting it.
flowchart LR
U["User identity"] --> H["Repeatable calculation on identity and feature"]
H --> B{"Which share does it fall into?"}
B -->|"First 40 percent"| A["Control value"]
B -->|"Next 30 percent"| V1["Variation one"]
B -->|"Last 30 percent"| V2["Variation two"]
What multivariate values are good for
- Testing different wordings, colours, or layouts.
- Trying several limits or thresholds on small audiences to see which performs best.
- Rolling out a new value slowly, by giving it a small weight and increasing it.
At a food fair, a stall hands out three flavours of sample, and every visitor is given one by a simple rule such as their ticket number. The stall owner counts which flavour sells best. A multivariate value is the ticket-number rule, giving each visitor a stable sample.
10The Ladder of Precedence: Which Value Wins?
With environments, segments, identities, and variations all possible, you need a clear picture of who beats whom.
From most specific to most general
When an application asks for a value, Flagsmith works down a ladder. The first rung that has an opinion decides the answer.
- Identity override: a value set for this exact person.
- Segment overrides: checked in priority order, and the first one whose rules match gives its value.
- Multivariate allocation: if the feature has variations, the user’s stable bucket picks one.
- Environment value: the normal value for the feature in this environment.
The exact interaction between segment overrides and multivariate options can depend on how you configure them. Always check how your setup behaves by testing with a few sample identities, and consult the current documentation for edge cases.
flowchart TD
Q["Application asks for a value"] --> I{"Identity override exists?"}
I -->|"Yes"| R1["Use the identity's value"]
I -->|"No"| S{"A segment override matches?"}
S -->|"Yes, highest priority first"| R2["Use that segment's value"]
S -->|"No"| M{"Feature has variations?"}
M -->|"Yes"| R3["Use the option from the stable bucket"]
M -->|"No"| R4["Use the environment value"]
A school has a general rule that homework is due on Friday. A class teacher might extend the deadline for her class. The head teacher might write a personal note allowing one pupil more time because of illness. When a pupil asks “when is my homework due?”, the answer comes from the most personal rule available, and falls back to the more general ones only when no personal rule exists.
Keeping it understandable
The more layers you use, the harder it is to explain why a user got a certain value. Prefer a few well-named segments over many overlapping ones, document each override, and use the dashboard’s tools for viewing a particular identity’s effective values when you investigate a puzzle.
A forgotten high-priority segment override can silently beat the value you just changed in the environment. If a change “does not work” for some users, check overrides before blaming the code.
11How an Application Reads a Value
Follow a single question from your code to Flagsmith and back.
The steps
Your application uses a Flagsmith SDK, a ready-made library that talks to the service. When the application starts, the SDK is set up with an environment key. When your code needs a setting, it asks the SDK for the value of a named feature, usually supplying a default, which is the value to use if nothing better is available. The SDK finds the feature in the flags it has received, and returns the value, converted to a type your code can use.
Where the answers come from
The SDK may have the answers from a recent request to Flagsmith, from a copy saved on the device, or from a downloaded set of rules held in memory on a server. In every case, the code asking the question is the same: “what is the value of this feature for this user?”
sequenceDiagram
participant Code as Your Code
participant SDK as Flagsmith SDK
participant FS as Flagsmith
Code->>SDK: Value of search-results-per-page, default 20
SDK->>SDK: Look in the flags already received
alt Flags are present
SDK-->>Code: The value, for example 30
else Flags missing or request failed
SDK-->>Code: The default, 20
end
SDK->>FS: Refresh in the background
FS-->>SDK: Latest values
The state and the value together
A feature has both a state and a value, so your code has a choice about how to treat a disabled feature that still has a value stored. Some teams read the value only when the feature is on, treating off as “use the built-in default”. Others read the value regardless. Decide on one convention for your team, write it down, and check how your SDK behaves, because mixed conventions lead to confusing bugs.
| Convention | Meaning of “off” | Good for |
|---|---|---|
| Off means use the built-in default | Ignore the stored value | Settings you want an easy way to switch back to normal |
| Always read the value | State is a separate matter | Pure settings that are always active |
A cook reading a recipe card finds “bake for twenty minutes” and uses it. If the card is missing, the cook uses the usual time they remember. The code’s default value is the cook’s memory: always there, ready to use when the card cannot be found.
12Client-Side and Server-Side: Reading Values in Each World
Where your code runs changes how values arrive and how much to trust them.
Server-side readers
A server runs on machines you control. Its SDK uses a secret server-side key, and can either ask Flagsmith for each user’s values, or download the whole environment’s rules once and answer in memory, which is called local evaluation. Local evaluation is very fast and reduces traffic, but changes reach the server only when the next refresh happens, commonly within about a minute by default.
Client-side readers
A browser or a mobile app runs on a device you do not control. Its SDK uses a public client-side key, asks Flagsmith for the values for one user, caches them, and uses them to shape the interface. The device receives only that user’s own results, never the full rules.
What to trust
Anything that reaches a client can be read and may be altered by the user. So values sent to a client must be harmless to reveal, and decisions of real importance must be checked on the server. A banner message in a value is perfect for a client. A secret address is not. A limit that merely adjusts the interface is fine on a client, while a limit that protects your servers must be enforced on the servers themselves.
| Question | Client-side | Server-side |
|---|---|---|
| Key | Public client key | Secret server key |
| Who decides the value? | Flagsmith | Flagsmith, or the server in local mode |
| Can the user read the value? | Yes | No |
| Best for | Texts, labels, interface settings | Limits, timeouts, thresholds, internal tuning |
| Freshness | On each fetch or refresh | Each request, or each document refresh |
Everyday use case: a limit and its message
A service limits how many exports a user can run each hour. The server reads the limit from a remote config value and enforces it. The browser reads a separate text value for the “limit reached” message. The server holds the real rule, and the client holds only the friendly wording.
A shop has a price list on the door that every passer-by can see, and a staff handbook in the back office that only employees can read. The door list shows what customers need. The handbook holds the rules that staff enforce. Client-side values are the door list. Server-side settings are the handbook.
13Data Flow: The Life of a Value Change
From a click in the dashboard to a changed behaviour in a user’s hands.
The journey
A person changes a value in the dashboard. Flagsmith saves the change and records it in the audit log. The new value is then copied to the layer that serves reads, so SDKs can see it. After that, each SDK learns of it in its own way: servers using remote evaluation on their next request, servers in local mode at their next refresh, and clients at their next fetch.
sequenceDiagram
participant P as Person in Dashboard
participant FS as Flagsmith
participant Log as Audit Log
participant Srv as Server SDK
participant Cli as Client SDK
P->>FS: Change value from 20 to 30
FS->>Log: Record who, what, and when
FS->>FS: Publish to the serving layer
Srv->>FS: Next refresh
FS-->>Srv: New value 30
Cli->>FS: Next fetch
FS-->>Cli: New value 30
The lifecycle of a setting
Define
Create the feature with a clear name, a description including unit and range, and an owner tag.
Wire up
The application reads the value with a safe default, validates it, and uses it.
Set per environment
Choose values for Development, Staging, and Production, and test them.
Tune
Adjust over time as you learn, using segments or variations where helpful.
Retire
When a setting becomes permanent, move it into code or configuration and delete the feature.
Not every setting should live forever
Remote config is for things that change or might need to change. A setting that has stayed the same for a year and will not change again is better off as a plain constant in code, which is simpler and cannot be altered by accident. Review old values regularly and ask whether each still earns its place.
A shop keeps a few prices on adjustable tags because they change often, and carves the shop’s name into stone above the door because it never will. Choose adjustable tags for settings that move, and stone for settings that stay.
14Deciding What Belongs in Remote Config
Not every setting deserves a dial. Good candidates share a few traits.
Good candidates
- Operational tuning: timeouts, retry counts, batch sizes, cache durations, thresholds.
- Limits and quotas: upload sizes, request rates, number of items, per plan.
- Messages and copy: banners, notices, labels, help links.
- Choices among a few options: which provider to use, which layout to show, which algorithm version.
- Gradual changes: any number you want to raise or lower in small steps while watching results.
- Emergency adjustments: values you may need to change fast during an incident.
Poor candidates
- Secrets: passwords, tokens, private keys. These belong in a secrets manager.
- Large data: long lists, documents, full catalogues. These belong in a database.
- Per-user data: a customer’s address or settings. These belong in your own data store.
- Things that never change: true constants are simpler in code.
- Settings that need deep review and migration: changes to data formats or schemas should go through code and tests, not a dial.
flowchart TD
A["A setting in the code"] --> B{"Is it secret?"}
B -->|"Yes"| S["Use a secrets manager"]
B -->|"No"| C{"Is it large or per-user data?"}
C -->|"Yes"| D["Use a database"]
C -->|"No"| E{"Might it need to change without a release?"}
E -->|"No"| K["Keep it as a constant in code"]
E -->|"Yes"| R["Use a remote config value"]
In a house, the front-door key goes in a safe, the family photos go in albums, the daily menu goes on a whiteboard, and the street name is carved on the gate. Each thing goes where it suits its nature. Remote config is the whiteboard: for what changes often, is harmless to see, and is small.
15Naming and Documenting Values
Good names and descriptions turn a pile of settings into a manual.
Names that explain themselves
A name is a permanent promise. Code will depend on it, so renaming later is costly. Choose names that say what the setting is, in which area, and in what unit. “payment-timeout-seconds” tells you three things at once. “timeout2” tells you nothing. A common pattern is area, then purpose, then unit, joined with dashes.
Descriptions that guide the next person
Fill in the description for every feature. Say what the value controls, the unit, the allowed range, what a sensible default is, and who owns it. If changing the value could affect cost or customers, say so.
Tags
Use tags to mark the owning team, the type of setting, and whether it is scheduled for review. Tags make it easy to filter a long list when you do a clean-up.
| Weak name | Better name | Why better |
|---|---|---|
| timeout | payment-provider-timeout-seconds | Says which timeout and its unit |
| limit | export-max-rows-per-request | Says what is limited |
| banner | site-maintenance-banner-text | Says the area and that it is text |
| new_value | search-results-per-page | Says the purpose, not its age |
| test3 | checkout-button-label-variant | Says what the variants change |
Agree on a naming pattern with your team before creating many features, and write it on one page. It is far cheaper to settle conventions early than to rename dozens of features later.
16Validation: Never Trust a Value Blindly
A remote value is typed by a human into a dashboard. Your code must treat it as input from outside, however friendly the source.
What can go wrong
- Typing mistakes: an extra zero, a missing digit, a stray space.
- Wrong type: text where a number was expected.
- Out-of-range numbers: zero, negative, or absurdly large values.
- Empty values: a blank where something was expected.
- Unknown choices: a mode name your code does not recognise.
- Broken structure: a block of structured text that cannot be read.
A sensible validation routine
- Convert the value to the type the code needs.
- Check the range or the allowed list. A timeout must be between one and thirty seconds. A mode must be one of the known names.
- Fall back to the last good value, or the built-in default, if the check fails.
- Log a warning that names the feature and the bad value, so a person can fix it.
flowchart TD
V["Value received from Flagsmith"] --> T{"Right type after conversion?"}
T -->|"No"| F["Use last good value or default, log a warning"]
T -->|"Yes"| R{"Within the allowed range or list?"}
R -->|"No"| F
R -->|"Yes"| U["Use the value"]
Everyday use case: clamping a rate limit
A service reads “requests-per-minute-limit”. The code accepts values from ten to ten thousand. If someone sets it to zero by mistake, which would block everyone, the code refuses it, logs a warning, and keeps the previous limit. The error is noticed in the logs, and fixed without an outage.
A kitchen oven has a safety cut-off. Even if someone turns the dial to a dangerous temperature, the oven refuses to go beyond its limit. Validation is that cut-off: the dashboard dial can be turned anywhere, but the application only accepts safe settings.
17A Typed Settings Layer in Your Own Code
Put one small module between your application and Flagsmith, and many problems disappear.
The idea
Instead of asking Flagsmith directly from many places, create one module in your own code that owns all remote settings. It has one clearly named function for each setting, such as “search page size” or “payment timeout”. Each function reads the value, converts it, validates it, applies a default, and returns a trustworthy result. The rest of the application only ever calls these functions.
What it gives you
- One place for defaults. Every setting has its safe default written once.
- One place for validation. Ranges and allowed lists are checked consistently.
- Clear types. The rest of the code never has to worry about text versus numbers.
- Easy testing. Tests can replace the module with fixed values.
- Easy change. If you ever switch tools, only this module changes.
- Good logging. The module can log the effective value at start-up and whenever it changes.
flowchart LR
A["Application code"] --> M["Your settings module"]
M -->|"Read, convert, validate, default"| SDK["Flagsmith SDK"]
SDK --> FS["Flagsmith"]
M --> L["Log effective values"]
A company has a receptionist who receives all outside calls, checks who is calling, and passes along only what staff need. Staff do not answer every call from strangers. The settings module is the receptionist for your remote values.
Give each function a short comment naming the Flagsmith feature it reads and the unit of its result. When someone searches the code for a setting name, they will land in one tidy place.
18Structured Values: Powerful but Risky
A block of structured text can hold many settings at once. Use it with open eyes.
Why teams use them
Sometimes several settings belong together: a timeout, a retry count, and a back-off factor, or the colours and text of a promotional banner. Putting them in one structured value means one feature to manage instead of five, and changes to the group happen at the same moment.
The risks
- Invalid structure. One missing bracket or comma can make the entire value unreadable.
- Shape drift. Someone adds, removes, or renames a field, and old code no longer understands it.
- Size. Big values slow every request, because they travel with all the flags.
- Hidden complexity. A dashboard text box is a poor place to edit a long, nested structure, and mistakes are easy.
- No type checking. The dashboard cannot tell you that a number field now holds text.
How to use them safely
- Keep them small. A handful of related fields is plenty.
- Add a version field. Let the code know which shape it is reading, so old and new can coexist.
- Validate every field. Treat each field like its own value, with a type, a range, and a default.
- Ignore unknown fields. A tolerant reader survives additions.
- Fall back as a whole. If the structure is unreadable, use the last good copy or the built-in defaults.
- Draft elsewhere. Edit and check the text in an editor that highlights mistakes, then paste it in.
| Approach | Strength | Weakness |
|---|---|---|
| Several simple values | Easy to read, type, and change one at a time | More features to manage |
| One structured value | Related settings change together | Easy to break, harder to review |
The mistake
A team keeps all of its application settings in one huge structured value, edited by hand in the dashboard. A missing comma during a late-night change makes the whole value unreadable.
Why it fails
Every setting, not just the one being changed, is lost at once. If the code has no fallback, the application misbehaves everywhere.
The fix
Split settings into small, separate values, or small structured groups. Validate on read, fall back to defaults, and draft long values in a proper editor before pasting.
19Safe Defaults and the Disabled State
Every read needs an answer to the question “what if there is no answer?”
Why defaults matter
The network will fail one day. The service may be slow. A feature may be deleted, misspelled, or missing from an environment. In every one of these cases, your code must still do something sensible. A default value written into the code is what saves the day.
Choosing a default
The best default is usually the value the application used before the setting became remote. It is known to work, because the code ran with it for months. If a new setting has no history, choose the safest, most conservative value: a generous timeout rather than a tiny one, a modest limit rather than none.
The disabled state
When the feature is off but still holds a value, decide what the code does. A common, safe convention is: “if the feature is off, use the built-in default and ignore the stored value”. This gives you a quick way to return to normal: just switch the feature off. Write the convention down, so everyone understands what “off” means for a value.
Where defaults live
Keep defaults in your settings module, not scattered across the code. A single list of defaults is easy to review, easy to test, and easy to update when you learn better numbers.
flowchart TD
A["Need the value"] --> B{"Answer received in time?"}
B -->|"No"| C{"Last good value available?"}
C -->|"Yes"| L["Use the last good value"]
C -->|"No"| D["Use the built-in default"]
B -->|"Yes"| E{"Feature on and value valid?"}
E -->|"Yes"| U["Use the received value"]
E -->|"No"| D
A pilot flying through cloud has a standard procedure for when instruments fail: fly straight and level at a safe height. The defaults in your code are that standard procedure, a known-safe behaviour for when the usual information is missing.
20Rolling Out a Value Change Gradually
Changing a number for everyone at once is a release too, and deserves the same care.
Config changes can break things
It is tempting to think of a value change as harmless, since no code is deployed. But a wrong timeout, limit, or switch of provider can cause as much damage as a bug, and a change made to everyone in one step can cause that damage everywhere at once. Many serious incidents in the industry begin with a configuration change rather than a code change.
Ways to roll out gradually
- Start with yourself. Use an identity override on your own account in Production.
- Then staff. Use a segment of employees.
- Then a small share. Use a multivariate feature, with the new value as a variation given a small weight, such as one or five percent.
- Widen in steps. Raise the weight while watching your graphs.
- Finish. Make the new value the environment default, and retire the variation.
Choose guardrail measures
Decide in advance which graphs show harm: errors, delays, complaints.
Try on your own account
Use an identity override and check the behaviour yourself.
Give a small share the new value
Use a low weight on a variation, and wait long enough to see a difference.
Widen while watching
Increase the share in steps, ready to return to the old value at once.
Make it the default
When the new value has proved itself, set it for everyone and clean up.
A chef changing a famous recipe does not alter the pot served to a full restaurant. They make a small batch, taste it, serve a few tables, and watch the plates come back. Only when the guests are happy does the new recipe go on the menu. Gradual value rollouts follow the same careful tasting.
A small percentage of a small audience is only a handful of people. Give each step enough time and traffic to show a problem, and do not read too much into tiny samples in either direction.
21Experiments with Values
Values are perfect for finding out which choice works better, by trying several on real users.
The basic idea
A multivariate feature gives different users different values in stable shares. If half of your visitors see one button label and half see another, and you measure how many click, you can learn which label works better. Flagsmith handles the splitting. To measure the results, you connect it to an analytics tool and compare the groups there.
Good experiments to run with values
- Wording of buttons, titles, and messages.
- The number of items shown in a list.
- Thresholds, such as the amount that unlocks free delivery.
- Time limits and reminders.
- Choice between two back-end algorithms, identified by name.
Doing it well
- State the question first. “Does the shorter label increase clicks?”
- Choose one main measure. Decide in advance what counts as success.
- Change one thing at a time. Otherwise you will not know what caused the difference.
- Run long enough. Cover whole weeks, so that weekday and weekend behaviour are both included.
- Record the assignment. Send the user’s variation to your analytics tool so results can be grouped.
- End the experiment. Make the winner the default and delete the variations.
flowchart LR
U["Users"] --> FS["Flagsmith assigns a stable variation"]
FS --> A["Group A sees value A"]
FS --> B["Group B sees value B"]
A --> AN["Analytics tool records behaviour"]
B --> AN
AN --> R["Compare results and choose a winner"]
A bakery tries two icing recipes on cupcakes. Half the customers receive recipe A and half receive recipe B, chosen by a fair rule. At the end of the week the baker counts which sold out first. The value is the recipe label, the rule is the stable assignment, and the sales count is the analytics.
Flagsmith does not itself decide a statistical winner. Use your analytics tool, and be cautious about drawing conclusions from small numbers of users or very short tests.
22Performance, Payload Size, and Caching
Values travel with the flags, so their size and the way they are cached affect every user.
Values ride along with every fetch
When an SDK asks for flags, it receives all features for the environment, each with its state and value. If your values are tiny, this is a small reply. If you have stuffed large pieces of text or structured data into values, every request carries that weight, for every user, on every device. Keep values short.
How many features are too many?
There is no magic number, but a project with thousands of features, many of them old, produces large replies and a crowded dashboard. Clean up regularly, and keep the active list lean.
Caching layers
- On servers: local evaluation keeps the whole environment in memory and answers instantly, refreshing on a schedule.
- On clients: SDKs keep answers in memory and often in local storage, so the app starts with saved values and updates in the background.
- In your settings module: you can cache the validated, converted value, so conversion and checking happen once per change, not on every read.
Read once, use many times
If code in a busy loop reads the same value thousands of times, converting and validating it every time wastes effort. Read the value once per request or once per refresh, store the validated result, and use that.
| Habit | Benefit |
|---|---|
| Keep values small | Smaller replies, faster fetches, less memory |
| Use local evaluation on busy servers | Answers in memory, very little traffic to Flagsmith |
| Cache on the device | Fast start, works offline |
| Validate once per change | Less repeated work |
| Delete old features | A lean list and a lean payload |
A traveller carries a backpack. A few small, useful items are no trouble. Fill it with bricks and every step becomes slow. Each value is an item in the backpack that every user carries on every journey, so pack only what is needed.
23Reliability: Stale Values, Outages, and Fallbacks
A good design assumes that one day the answer will be late, old, or missing.
Three kinds of trouble
- Missing: the service cannot be reached, or the feature does not exist in this environment.
- Late: the answer arrives slowly and may hold up the code waiting for it.
- Stale: the application is using an older value than the one now set, because a refresh has not happened or has silently stopped.
Layers of protection
- Short timeouts on any request, so a slow service never holds up your application.
- Cached values from the last successful fetch, used while fresh ones cannot be obtained.
- Built-in defaults for everything, used when there is no cache.
- Validation so that a bad value is never used.
- Circuit breakers that stop asking a failing service for a while and use fallbacks instead.
Detecting staleness
Stale values are quiet failures. A server in local mode that stops refreshing keeps using old numbers, and nothing shouts. Record the age of the rules held in memory and alert if it grows far beyond the refresh interval.
stateDiagram-v2
[*] --> Normal
Normal --> Degraded: "Refresh fails"
Degraded --> Normal: "Refresh succeeds"
Degraded --> Alert: "Age exceeds limit"
Alert --> Normal: "Refresh succeeds"
A ship’s captain who loses the radio keeps sailing by the last weather report, but also notes how old the report is. After a few hours, the captain slows down and takes extra care. Your application should behave the same way: use the last known value, but raise an alarm when it gets too old.
Practise the failure. In a staging environment, block the network path to Flagsmith and watch what the application does. If anything surprises you, fix the defaults and fallbacks before real users find the problem.
24Security: What Never to Put in a Value
A convenient place to keep settings is not automatically a safe place to keep secrets.
Never store secrets
Passwords, private keys, access tokens, and connection strings with credentials do not belong in remote config values. Values can be seen by people with dashboard access, they appear in audit history, and, for client-side use, they are delivered to devices where users can read them. Keep secrets in a dedicated secrets manager.
Assume client values are public
Anything sent to a browser or phone can be read by the person holding it. Do not put internal addresses, private pricing logic, or unreleased plans in values that reach clients. Even if you hide the value in the interface, it still travelled over the network.
Do not use values as permissions
A value that says “this user may export” decides what the interface shows. It must not be the only guard. The server must check permission for real, every time, because clients can be tampered with.
Protect who may change values
Changing a value is a production change. Limit who can edit Production, use approval workflows where your plan supports them, and keep the audit log on. Give automation, such as scripts that change values, narrow credentials and rotate them regularly.
Mind the data inside traits
Segment rules use traits. Send only the facts needed for targeting, such as plan and region, and use internal identifiers rather than emails or names.
| Item | Safe in a value? | Better home |
|---|---|---|
| Page size, timeout, limit | Yes | Remote config |
| Banner wording | Yes | Remote config |
| Public help link | Yes | Remote config |
| Password or token | No | Secrets manager |
| Private key | No | Secrets manager |
| Customer personal data | No | Your own database |
| Internal network address | Avoid, especially for clients | Server configuration |
The mistake
A team stores a third-party access token in a remote config value so that “we can rotate it without a release”.
Why it fails
Anyone with dashboard access can read it, it sits in the history of changes, and if the value is ever sent to a client, it reaches every user.
The fix
Store the token in a secrets manager that supports rotation, and let the application fetch it from there. Keep only non-secret settings in Flagsmith.
25Governance: Owners, Approvals, and Scheduling
As more people can change more values, rules keep the system trustworthy.
Give every value an owner
For each feature, a named person or team is responsible. They decide when it changes, answer questions about it, and remove it when it is no longer needed. Record the owner in a tag or the description.
Levels of access
A simple and effective rule is three tiers. Everyone on the engineering team may change values in Development. A wider group, including testers and product managers, may change Staging. A small group, or an approval workflow, controls Production. Where your plan includes finer roles, use them.
Change requests
In plans that offer them, change requests let one person propose a change and another approve it before it takes effect, much like a code review. Use them for values that touch money, safety, or legal rules, such as pricing thresholds and rate limits.
Scheduled changes
Where available, a change can be scheduled for a future time. A promotional banner can go live at midnight on a holiday without anyone being awake, and a second scheduled change can restore normal text afterwards. Scheduling also helps with changes that must happen outside busy hours.
The audit log
Flagsmith records who changed what and when. Use it to answer “what changed?” during incidents, to review activity, and to demonstrate control to auditors.
Propose
An engineer or product manager proposes the new value, with a reason.
Review
A second person checks the value, its range, and who is affected.
Apply or schedule
The change is applied at once or at an agreed time.
Watch
The team watches the graphs for the agreed period.
Record
The audit log holds the history, and notes explain the reason.
In a hospital, a doctor writes a prescription, a pharmacist checks it, and a nurse administers it and records the time. Each step catches possible mistakes. A good process for changing important values uses the same chain of care.
26Monitoring: Seeing What Your Values Are Doing
If you cannot see a value’s effect, you cannot tell whether a change helped or hurt.
Log the effective value
Have your settings module log the value actually in use, with the feature name, at start-up and whenever it changes. When someone asks “what timeout was the payment service using at three in the afternoon?”, you can answer from the logs.
Mark changes on graphs
Send value-change events from Flagsmith to your monitoring tool using webhooks or integrations, so a marker appears on your error and speed graphs at the exact moment of a change. This makes the connection between a change and its effect obvious.
Measure what the value affects
- For a timeout: the rate of timeouts and the rate of failed payments.
- For a page size: the page load time and the number of next-page clicks.
- For a rate limit: the number of rejected requests and the load on the system.
- For a message: the number of support contacts and clicks on its link.
Watch the machinery too
- Age of the rules held in server memory.
- Success rate of refreshes.
- How often defaults were used instead of real values.
- Number of validation failures, which suggests mistakes in the dashboard.
flowchart LR
FS["Flagsmith change events"] --> MON["Monitoring tool"]
APP["Application logs of effective values"] --> MON
MET["Metrics on what the value affects"] --> MON
MON --> DASH["Graphs with change markers"]
MON --> AL["Alerts on staleness and failures"]
A gardener who changes the watering schedule writes the date in a notebook, then watches the plants over the following days. If the leaves droop, the notebook shows exactly when the change was made. The change markers on your graphs are that notebook.
27Rollback and Recovery
The best time to plan how to undo a change is before you make it.
The goal
When a value change goes badly, you want to return to a good state quickly and calmly. Because values live outside the code, a rollback is just another value change, which can be far faster than redeploying software.
Before you change
- Note the old value. Write it in the change request, the ticket, or a chat message, so nobody has to dig for it.
- Know the speed. Understand how long the change will take to reach servers and devices, so you know how long to wait.
- Prepare the rollback. If your plan supports scheduling, you may even schedule a return to the old value as a safety net.
- Decide the trigger. Write a sentence such as “if the error rate stays above the limit for ten minutes, restore the old value”.
During an incident
- Check the audit log for recent changes to values and flags.
- Restore the previous value of the most likely suspect.
- Wait for the change to propagate, and watch the graphs.
- If it was not the cause, restore the next suspect, and keep notes.
Where history comes from
The audit log shows past changes and who made them. Some plans offer versioning of feature states, which keeps earlier versions available to compare or restore. Check which of these your plan includes, and rely on them, but still keep your own notes of important changes.
flowchart TD
A["Problem noticed"] --> B["Check audit log for recent value changes"]
B --> C{"Suspect found?"}
C -->|"Yes"| D["Restore the previous value"]
C -->|"No"| E["Look at code deployments and other causes"]
D --> F["Wait for propagation and watch graphs"]
F --> G{"Problem gone?"}
G -->|"Yes"| H["Record what happened and why"]
G -->|"No"| B
A good cook writes the old oven temperature on a sticky note before turning the dial. If the cake burns, the cook knows exactly where to turn it back. A rollback note is that sticky note: tiny, easy, and priceless in a hurry.
Remember the delay. If servers refresh once a minute and apps refresh on launch, then “restore the old value” does not instantly end a problem. Plan your incident notes with the real delays in mind, so nobody panics when the graphs do not move at once.
28Remote Config Compared with Other Ways to Hold Settings
Remote config is one tool among several. Each has its place.
The common alternatives
- Constants in code: simplest and safest, but every change needs a release.
- Configuration files: shipped with the application, changed with a deployment.
- Environment variables: set when a process starts, usually needing a restart to change.
- A database table: flexible and under your control, but you must build the editing screens, history, and targeting yourself.
- Cloud parameter stores: managed key-value services offered by cloud providers, good for server settings and secrets, usually without user targeting or rollouts.
- A remote config service such as Flagsmith: a dashboard, targeting, rollouts, history, and SDKs, ready-made.
| Option | Changes without a release? | Per-user targeting? | History and audit? | Good for |
|---|---|---|---|---|
| Constants in code | No | No | In version control | True constants |
| Config files | No, usually a deployment | No | In version control | Stable settings per environment |
| Environment variables | Needs a restart | No | Depends on tooling | Deployment-specific settings |
| Database table | Yes | Only if you build it | Only if you build it | Custom needs |
| Cloud parameter store | Yes | Rarely | Often, basic | Server settings and secrets |
| Flagsmith remote config | Yes | Yes, via segments and identities | Yes, audit log | Tunable, targetable settings |
Using them together
Most healthy systems use several. Secrets go in a secrets manager. Deployment details such as database addresses go in environment variables or configuration files. True constants stay in code. Tunable, targetable, frequently changing settings go in remote config. Each tool does what it does best.
A kitchen has a safe for valuables, labelled jars for ingredients, a printed recipe book, and a whiteboard for daily specials. Nobody argues over which is best, because each has its job. Remote config is the whiteboard.
29Real-World Usage Scenarios
Common ways teams use remote config values. These describe general practices, not any named customer.
Tuning a timeout during an incident
A payment provider slows down on a busy evening. The engineer on call raises “payment-provider-timeout-seconds” from eight to twelve and lowers “payment-retry-count” from three to one, to avoid piling up requests. Servers pick up the new numbers within about a minute, the failure rate falls, and the changes are restored once the provider recovers. No release was needed.
A maintenance banner with a message
A flag turns the banner on and a text value holds the wording. The team schedules the change for the start of a maintenance window and a second change for the end. The wording can be edited by the support team, with approval, without involving developers.
Plan-based limits
A product has free, pro, and enterprise plans. One feature, “max-projects”, has a base value of three, with segment overrides of twenty for pro and unlimited-style large numbers for enterprise. When pricing changes, the product team edits values, and engineers do nothing.
Regional wording
A retailer shows different shipping messages in different regions. A segment for each region gives a different text value, so wording can be corrected by the local team, without waiting for a code release.
Choosing a provider by name
A value holds the name of the email provider to use. The code knows two providers, and the value selects between them. If one has an outage, the value is changed to the other, and the fix takes a minute.
Mobile apps and old versions
A mobile app reads a “minimum-supported-version” value. When a serious bug is found in an old version, the team raises the value, and older apps show a polite “please update” screen on their next refresh, long before an app store release could have reached everyone.
Experimenting with a threshold
An online shop tests whether a free-delivery threshold of forty or fifty currency units leads to larger baskets. A multivariate value gives each half of the visitors a different threshold, and analytics compare the results.
30Design Patterns for Remote Config
A few proven shapes cover most uses.
Operational dial
A number the on-call engineer can change in an incident, such as a timeout or batch size, with a safe range.
Switch plus message
A flag decides whether a notice is shown, and a value holds its wording.
Tiered limits
One feature with segment overrides for each plan or tier.
Named selector
A value that holds the name of one of several built-in choices, such as a provider or algorithm.
Minimum version gate
A version number below which apps show an update notice.
Gradual value change
A multivariate feature that moves users from the old value to the new in steps.
Maintenance mode
A state and value pair that puts an area into read-only mode with a message.
Typed settings layer
One module in your code that reads, validates, and defaults every value.
How the patterns combine
Real systems blend them. An emergency “reduce load” switch might be an operational dial, a switch plus a message, and a named selector at once: the state turns on a reduced mode, the value chooses the level, and a text value tells users what is going on. Keep each piece simple, and let them work together.
flowchart LR
S["State: reduced mode on"] --> A["Application reduces load"]
V1["Value: level 2"] --> A
V2["Value: message text"] --> U["Users see a clear notice"]
A --> U
A lighthouse has a lamp, a rotation speed, and a foghorn pattern, all adjusted together according to the weather. Each is a simple control. Together they provide a clear signal. Remote config patterns work the same way: simple parts, combined with purpose.
31Anti-Patterns and Common Mistakes
These traps catch teams again and again.
Trusting the value without checking
The code uses whatever arrives. A typing mistake in the dashboard becomes a production incident.
The fix
Convert, check ranges, fall back to the last good value, and log a warning.
A configuration database in disguise
Hundreds of values, some very large, hold data that really belongs in a database. Replies become big and the dashboard becomes unmanageable.
The fix
Keep values small and few. Move data to a real data store.
Changing production values without review or watching
Anyone can edit a live number, with no approval and no one watching the graphs.
The fix
Limit who can change Production, use change requests for sensitive values, and watch guardrail graphs after each change.
No default in the code
If the value is missing, the application errors or uses a nonsense value.
The fix
Give every setting a safe default in one central place.
Forgotten overrides
Old segment and identity overrides silently beat the value you changed, leaving some users on outdated settings.
The fix
Document each override, review them regularly, and check overrides first when a change “does not work for some users”.
More mistakes to avoid
- Unclear names and missing units. Nobody knows whether “thirty” means seconds or items.
- Secrets in values. Use a secrets manager.
- Environment drift. Staging no longer resembles Production, so tests mislead.
- Mixed conventions about the disabled state. Some code reads the value when off, some does not.
- Settings that should be constants. A value that never changes is a risk with no benefit.
- Pointing a test app at Production. A classic way to change live values by accident.
- Ignoring propagation delay. Expecting an instant effect on every server and device.
32Best Practices Checklist
If you keep one page of this guide, keep this one.
Name with area and unit
For example, payment-provider-timeout-seconds. Never “timeout2”.
Describe every value
Meaning, unit, allowed range, default, and owner.
One settings module
Read, convert, validate, and default in one place.
Validate always
Check type and range, and fall back to the last good value.
Safe defaults
The value the code used before is the best default.
No secrets
Use a secrets manager for passwords, tokens, and keys.
Server enforces, client shows
Values shape the interface; the server checks real permissions.
Change gradually
Try on yourself, then a small share, then everyone.
Owners and approvals
Name an owner, and require review for sensitive values.
Log and mark changes
Log effective values and mark changes on your graphs.
Note the old value
Write down what to restore before you change anything.
Retire what is settled
Move permanent settings into code and delete the feature.
33Testing Remote Config
Values add paths through your code. Each one deserves a test.
Test the code, not the live service
Automated tests should not depend on the live Flagsmith service or on whatever someone has set in the dashboard today. Use the offline mode of an SDK, or a small replacement that returns the exact values a test needs. Tests then run fast, give the same result every time, and cannot be broken by someone editing a setting.
What to test
- Normal values: the code behaves correctly at typical, smallest, and largest allowed values.
- Bad values: wrong type, empty, zero, negative, and absurdly large values are rejected and replaced by a fallback.
- Missing values: when the feature does not exist, the default is used.
- Disabled state: the code treats “off” according to your team’s convention.
- Changes while running: if the value changes during use, nothing breaks, and long-running operations behave sensibly.
- Different groups: users in each segment receive the expected value.
Test in a real environment too
Keep a Staging environment where values are set on purpose, and run an end-to-end test against it. This proves that keys, addresses, and rules work together, which fakes in unit tests cannot show.
| Test | Input | Expected result |
|---|---|---|
| Typical value | Twenty items per page | Twenty results shown |
| Zero value | Zero items per page | Rejected, default used, warning logged |
| Text where a number is expected | “twenty” | Rejected, default used, warning logged |
| Missing feature | No such feature | Default used |
| Feature off with a stored value | Off, value forty | Built-in default used, per convention |
| Segment override | User on the enterprise plan | Enterprise limit applied |
Before an airline opens a new route, pilots practise in a simulator with calm weather, storms, and engine trouble. They do not wait for real storms to find out what happens. Testing your values with good, bad, and missing inputs is your simulator.
34Advantages, Disadvantages, and Trade-offs
An honest look at what remote config gives you and what it asks of you.
Advantages
- Change settings in minutes without a release.
- Different values per environment, group, and person.
- Gradual rollouts and experiments with the same tool.
- Fast response in incidents.
- Non-engineers can safely adjust approved settings.
- Audit history of who changed what.
- Works on mobile apps without waiting for app stores.
Disadvantages
- A change can cause an outage as easily as code can.
- Values are weakly typed, so mistakes are easy to type.
- Behaviour depends on state outside the code, which is harder to reason about.
- Overrides and layers can confuse people.
- Propagation is not instant.
- Unmanaged values pile up and become clutter.
- Adds a dependency on another service.
The main trade-offs in plain words
| Choice | You gain | You give up |
|---|---|---|
| Setting in remote config | Speed of change and targeting | The safety of a reviewed, tested code change |
| Many small values | Easy to read and change | More features to manage |
| One structured value | Related settings change together | Easy to break, harder to review |
| Local evaluation on servers | Speed and low load | Instant freshness |
| Values on clients | Responsive interface changes | Anything sent can be read by the user |
| Wide edit permissions | Convenience and speed | Control and safety |
A car’s driver can adjust the seat, the mirrors, and the air conditioning while driving, but cannot safely rebuild the engine. Remote config is the set of dials within the driver’s reach. It is wonderful for adjustments, and unsuitable for work that needs a garage.
35Troubleshooting Guide
When a value does not behave as expected, start with the symptom.
| Symptom | Likely cause | What to check |
|---|---|---|
| Application always uses the default | Wrong key or environment, feature name misspelled, or request blocked | Key and environment, exact name and case, network errors |
| Dashboard change not seen on servers | Refresh interval has not elapsed, or refresh is failing | Age of rules in memory, refresh logs, interval setting |
| Dashboard change not seen in the app | Cached values or no refresh yet | When the app last fetched, refresh rules, app version |
| Some users see a different value | Segment or identity override, or multivariate share | Overrides on the feature, and the user’s effective values |
| Value arrives as text instead of a number | SDK returns the stored string | Convert in your settings module |
| Value seems ignored though stored | Feature is off and code ignores the value when off | The team’s convention for the disabled state |
| Application misbehaves after an edit | Typing mistake or invalid structure | The audit log, then the value itself; add validation |
| Same user sees different values over time | Identifier changes, or traits change segments | Identifier stability and trait stability |
| Staging works but Production fails | Environment drift | Compare values and overrides across environments |
| Replies from Flagsmith are large | Big values or too many features | Value sizes and old features to delete |
A calm routine for any problem
- Check what changed. Read the audit log and recent deployments first.
- Check the effective value. Look at what a particular identity actually receives, including overrides.
- Check the code’s view. Look at the logged effective value in your application.
- Check timing. Has enough time passed for caches and refreshes?
- Fix and guard. Correct the cause, then add validation, logging, or a test so it is caught sooner next time.
36A Worked Example: Tuning a Payment Timeout from Start to Finish
Let us follow one setting through its whole life, to see how every idea in this guide fits together.
An online store calls an outside payment provider whenever a customer pays. The code waits a certain number of seconds for the provider to reply and, if nothing arrives, tries again a few times. For years, these numbers were written into the code. The team decides to turn them into remote config values.
Step 1: Define the features
The team creates two features. The first is “payment-provider-timeout-seconds”, described as “how long to wait for the payment provider before giving up, in seconds, allowed range one to thirty, default eight, owned by the payments team”. The second is “payment-retry-count”, described in the same careful way with an allowed range of zero to five and a default of two.
Step 2: Wire them into the code
A settings module reads each value, converts it to a whole number, checks the allowed range, and falls back to the default if anything is wrong. The payment code asks the settings module, never Flagsmith directly. The module also logs the effective values when the service starts and whenever they change.
Step 3: Set the values per environment
In Development, the timeout is thirty seconds, to give engineers time to debug. In Staging, it is ten. In Production, it is eight. The same two features exist everywhere, with different values in each place, and a change in one never touches the others.
Step 4: A busy evening
One night, the provider begins to answer slowly. Failed payments rise on the team’s graph. The engineer on call checks the audit log, sees no recent changes, and decides to tune the settings. They note the old values, then raise the timeout to twelve and lower the retry count to one, so that slow requests are not multiplied by retries.
Step 5: The change spreads
Flagsmith saves the change and records it in the audit log, and a webhook posts a message to the team chat. Servers using local evaluation pick up the new values at their next refresh, within about a minute. A marker appears on the failure-rate graph at the moment of the change, and the line starts to fall.
Step 6: Recovery and clean-up
An hour later the provider recovers. The engineer restores the original numbers, using the values they wrote down, and the marker on the graph shows the return to normal. In the morning, the team writes a short note in their incident record explaining what happened and what was changed. They also decide that the retry count deserves an approval step in future, because it affects customers directly, and enable a change request for it.
sequenceDiagram
participant Eng as On-Call Engineer
participant FS as Flagsmith
participant Chat as Team Chat
participant Srv as Payment Servers
participant Mon as Monitoring
Mon->>Eng: Failure rate rising
Eng->>FS: Raise timeout to 12 and lower retries to 1
FS->>Chat: Webhook announces the change
FS->>Mon: Change marker on the graph
Srv->>FS: Next refresh within about a minute
FS-->>Srv: New values
Mon->>Eng: Failure rate falling
Eng->>FS: Restore the original values later
Prepared in advance
Clear names, descriptions, ranges, defaults, and a settings module that validates.
Used in a crisis
Two numbers changed in minutes, with the old values written down.
Seen and recorded
A graph marker, a chat message, and an audit log entry told the whole story.
Learned from
The team tightened governance for the riskier value afterwards.
Think of a captain easing the throttle and adjusting the rudder when a storm arrives. The ship has not been rebuilt. The crew has simply moved a few well-labelled controls, noted the settings in the log, and returned them when the weather cleared. That is exactly what the payments team did with two remote values.
37Moving Hard-Coded Settings into Remote Config
Most teams do not start from scratch. They already have settings scattered through their code, and need a calm way to move them.
Start with an inventory
Search your code for numbers and phrases that might need to change: timeouts, limits, page sizes, thresholds, messages, and provider names. List each one with where it lives, what it does, who owns it, and how often it has changed in the last year. You will often find that most never change, and a handful change often. Those few are your first candidates.
Choose a few good candidates
Pick settings that are small, harmless to reveal, easy to understand, and that the team has actually wished to change quickly. Avoid starting with the most critical setting in the company. Early successes build trust.
Build the settings module first
Before moving any values, create the module that will read, convert, validate, and default them. Fill it with the current hard-coded numbers as defaults. At this point nothing has changed in behaviour, because Flagsmith has no values yet and the defaults match what the code always did.
Create the features with matching values
For each chosen setting, create a feature in Flagsmith with the current value in every environment, and a good description. Because the value matches the default, the application’s behaviour stays the same.
Compare, then trust
For a time, let the module log whenever the Flagsmith value differs from the old hard-coded one. When the two agree for a good period, and you have confirmed that the application reads values correctly, you are free to change values from the dashboard with confidence. Finally, remove the old constants from the code, leaving only the defaults in the settings module.
flowchart LR
A["Inventory settings"] --> B["Pick a few good candidates"]
B --> C["Build settings module with current values as defaults"]
C --> D["Create features with the same values"]
D --> E["Compare and log differences"]
E --> F["Change values from the dashboard"]
F --> G["Remove old constants"]
The big-bang migration
A team moves every setting at once in a single weekend, with new numbers chosen along the way. Several values are slightly wrong, and nobody can tell which problems come from the move and which from the new numbers.
The fix
Move settings in small groups, with unchanged values first. Change numbers only after the move is proven, one at a time, and watch each change.
Moving house goes best when you pack room by room, label every box, and unpack the kitchen before you rearrange the furniture. Carry your settings across unchanged first, then rearrange them once everything is safely in the new place.
38A Production-Readiness Checklist for Remote Config
Before you rely on remote config for something important, walk through these questions with your team.
| Area | Question to answer | A good answer sounds like |
|---|---|---|
| Naming | Can a stranger tell what each value does? | Names include area, purpose, and unit, and descriptions state range and default |
| Defaults | What happens if no value arrives? | Every setting has a safe default in one module |
| Validation | What if a bad value is typed? | Type and range are checked, the last good value is kept, and a warning is logged |
| Secrets | Is anything secret stored in a value? | No. Secrets live in a secrets manager |
| Clients | What can a user see or change? | Client values are harmless to reveal, and the server enforces real permissions |
| Environments | Could a test app change live values? | Each environment has its own keys, loaded from configuration |
| Speed of change | How long until a change takes effect? | We know the refresh interval for servers and the refresh rules for apps |
| Rollout | How do we change a sensitive value safely? | Identity override first, then staff, then a small share, with guardrail graphs |
| Approvals | Who may change Production? | A small named group, with change requests for sensitive values |
| Visibility | Will we notice a bad change quickly? | Effective values are logged and changes are marked on graphs |
| Rollback | How do we undo a change? | The old value is noted before each change and the audit log is checked first in incidents |
| Hygiene | Who removes settled values? | Owners review values regularly and move permanent settings into code |
| Testing | Do tests cover bad and missing values? | Tests use an offline replacement and include out-of-range, empty, and missing cases |
How to use the checklist
Hold a short review before your first important setting goes live, and again each time your use grows in a big way. Go through each row and ask for a real answer, not a hope. Any row where the team hesitates is a place where something will eventually go wrong. Write down each gap, give it an owner, and fix the most dangerous first.
Make the checklist part of your regular review of values. Teams that look at their settings together every few months catch forgotten overrides, drifting environments, and silent refresh failures long before any of them cause an incident.
39Glossary of Terms
Every important word in this guide, in one place.
| Term | Meaning |
|---|---|
| Remote config | Settings kept outside the code, changed from a dashboard and read by applications while they run. |
| Remote config value | The data, such as a number or text, attached to a feature. |
| Feature | The named item in Flagsmith that has a state and may carry a value. |
| State | Whether a feature is on or off in an environment. |
| Project | A container for one product or application and its features. |
| Environment | A stage such as Development, Staging, or Production, each with its own states and values. |
| Identity | A unique ID for one user, device, or account. |
| Trait | A named fact about an identity, used by segment rules. |
| Segment | A reusable group of identities defined by rules over traits. |
| Segment override | A different state or value for members of a segment. |
| Identity override | A different state or value for exactly one identity. |
| Multivariate feature | A feature with several weighted values handed out to stable shares of users. |
| Control value | The standard value that variations are compared against. |
| Default value | The value written into code, used when no real value is available. |
| Validation | Checking that a value has the right type and range before using it. |
| Settings module | A single piece of your own code that reads, validates, and defaults all remote values. |
| Structured value | A value holding a small block of structured text, such as JSON. |
| Local evaluation | A server SDK answering from a downloaded copy of the rules held in memory. |
| Staleness | Using an older value than the one now set. |
| Change request | A proposed change that another person must approve before it takes effect. |
| Scheduled change | A change set to happen at a future time. |
| Audit log | A record of who changed what and when. |
| Guardrail metric | A measure of product health watched during a rollout, such as error rate. |
| Drift | Values in different environments slowly becoming inconsistent for no recorded reason. |
40Frequently Asked Questions
41Summary and Key Takeaways
Remote config values turn the small numbers and words buried in your code into dials you can reach from a dashboard. Flagsmith stores them alongside flags, lets you set them per environment, group, and person, hands them out in controlled shares for experiments, and records every change. Used with care, they make your software faster to tune, safer to change, and easier to rescue in a crisis. Used carelessly, they become one more source of outages, so good names, safe defaults, validation, and gradual rollouts matter as much as the tool itself.
Key Takeaways
- What it is: a remote config value is data, such as a number or text, attached to a feature and changed from a dashboard without a release.
- Flag versus value: a flag answers whether, a value answers how or what, and one feature can hold both.
- Targeting: values can differ by environment, segment, identity, and weighted variation, and the most specific rule wins.
- Trust nothing blindly: convert, check range and type, fall back to the last good value or a default, and log warnings.
- Keep it small and safe: no secrets, no large data, no permissions decided by a client-side value.
- Change like a release: try on yourself, then a small share, watch guardrail graphs, note the old value, and keep the audit log.
- Keep it tidy: clear names with units, descriptions and owners, one settings module in your code, and a regular clean-up of settled values.