The Default Value in Flagsmith
The answer a flag gives when nothing more specific applies, and the answer your application falls back on when no answer arrives at all. Learn the four places a default lives, how they differ, and how to choose each one so that surprises become boring.
Picture a hotel night receptionist. When a guest arrives with a booking, the receptionist gives the room that was reserved. When a guest arrives with a special request, such as a quiet room, the receptionist follows the request. But what if the computer system is down and nobody can find a reservation? The receptionist does not freeze. There is a plan: a standard room, a standard rate, and a note to sort it out in the morning. That plan, decided long before the emergency, is a default.
Software needs exactly the same kind of plan. A feature flag answers questions such as “should this screen be shown?” or “how many results should we display?” Most of the time Flagsmith answers according to rules. But sometimes no rule matches, or the answer cannot be fetched, or the flag does not exist. In each case something must still happen, and what happens is the default value. Choosing defaults badly is one of the quietest ways to cause an outage. Choosing them well is one of the cheapest ways to prevent one.
This guide explains every kind of default in Flagsmith from the ground up. No previous knowledge is assumed. Each new word is explained when it first appears, and each idea comes with a picture from everyday life.
1What Does “Default Value” Mean in Flagsmith?
The phrase is used in several ways, and mixing them up is the number one source of confusion. This chapter separates them.
First, the basics
A feature flag is a switch inside software that decides whether a behaviour is active. Flagsmith is a platform that stores those switches, lets people change them from a dashboard, and delivers the answers to applications through small libraries called SDKs. A value is an optional piece of information that a flag can carry along with its on or off state, such as a number or a short piece of text. That is called remote configuration.
The word “default”
A default is the answer used when no more specific answer exists. In everyday life, the default font in a document is what you get if you do not choose another one. In Flagsmith there are four distinct defaults, each living in a different place and used at a different moment.
The creation default
The starting state and value you set when you first create a feature. It decides what every Environment begins with.
The Environment default
The baseline answer of a feature inside one Environment, used for everyone who matches no segment or personal override.
The control value
For features that split users between versions, the original value that people receive when they are not placed in any variation.
The default in your code
The fallback your application uses when Flagsmith gives no answer at all, because of a network failure or a missing flag.
Think of a restaurant. The recipe card in the kitchen says how a dish is normally made. That is like the creation default. The standing house rule says “unless the customer asks otherwise, serve it medium”. That is like the Environment default. If the order slip is lost entirely, the waiter serves the house special, which is like the default in code. Four levels, four different moments, one shared idea: what happens when nothing more specific is known.
When someone says “the default” in a team meeting, ask which one they mean. The creation default and the default in code can be completely different answers for the same flag, and many bugs hide in that gap.
2Why Defaults Deserve Careful Thought
Defaults rarely get attention, because when they work nobody notices. They matter most on the days everything else is going wrong.
The problem defaults solve
Every system must decide what to do in situations nobody planned for. A flag platform is a network service, and network services are sometimes slow, sometimes unreachable and sometimes asked for things that do not exist. If your application has no plan for these moments, it will invent one by accident: it may crash, it may show a blank screen, or it may quietly turn a feature on that should have been off. A deliberate default turns an unpredictable accident into a predictable, harmless behaviour.
A principle older than the internet
In 1975, two computer scientists, Jerome Saltzer and Michael Schroeder, published a famous paper on protecting information in computer systems. One of their design principles is called fail-safe defaults. It says that when something goes wrong or is unspecified, the system should lean towards the safe outcome rather than the permissive one. A door that cannot reach its lock controller should stay locked, unless it is a fire exit, in which case it should open. The principle is not “always choose off”. It is “choose the answer that causes the least harm”.
Lifts are built so that if the power fails, the brakes clamp shut rather than release. Nobody asked the lift in the middle of the emergency what to do. The engineers decided years earlier, in a quiet office, which direction failure should lean. Your flag defaults are the brakes of your product.
What big companies teach us
Engineering teams at companies such as Netflix and Amazon have spoken publicly about designing for failure: assuming that any dependency can be slow or unavailable and making sure the customer still gets a reasonable experience. Netflix is widely known for the idea that a missing recommendation row should never stop a video from playing. A flag lookup is one more dependency. If it fails, the product should drop back to a calm, known behaviour and carry on.
The cost of an unthought default
An unthought default rarely announces itself. It sits quietly in the code for months, and then one afternoon a network problem or a typo causes it to be used. The cost is not the moment of failure but the confusion afterwards: the team asks why customers saw something nobody planned, and nobody can say who decided it. Writing the decision down in advance, even in one sentence, turns that confusion into a lookup. The effort is small, the benefit arrives on the worst day of the year, and that is the best kind of engineering trade.
3The Map: How the Four Defaults Fit Together
A picture of the whole journey makes each individual default easier to place.
Follow a feature from the moment it is created to the moment a user sees its result. The creation default sets the starting state. Each Environment then holds its own baseline, which is the Environment default. Segment and identity overrides may change the answer for chosen people. And if the application cannot obtain an answer, it uses the default written in its own code.
flowchart TD
A["Feature created with a creation default"] --> B["Each Environment holds its own baseline value"]
B --> C{"Does the user have an identity override?"}
C -- Yes --> R1["Answer: identity override"]
C -- No --> D{"Does the user match a segment override?"}
D -- Yes --> R2["Answer: segment override"]
D -- No --> R3["Answer: Environment default"]
R1 --> E["SDK delivers the answer to the app"]
R2 --> E
R3 --> E
E --> F{"Did an answer arrive?"}
F -- Yes --> G["App uses the answer"]
F -- No --> H["App uses the default written in its code"]
| Default | Where it lives | When it is used | Who sets it |
|---|---|---|---|
| Creation default | The feature creation form in a Project | When the feature is first made | The engineer creating the feature |
| Environment default | The feature state inside one Environment | For everyone matching no override | People with permission for that Environment |
| Control value | The feature’s original value, in a split feature | For users not placed in a variation | The team running the experiment |
| Default in code | Your application’s source code | When no answer arrives | The developers of the application |
The first three defaults live inside Flagsmith, and a person can change them in the dashboard. The fourth lives in your code, and only a new release can change it. That difference in who can change what, and how fast, explains most of the advice in this guide.
Which default answers which question?
A quick way to keep the four straight is to attach a question to each. The creation default answers “what should this feature start as?” The Environment default answers “what is the general rule in this stage?” The control value answers “what does the ordinary user get while an experiment runs?” The default in code answers “what do we do if nobody answers at all?” If you can state which question you are asking, you almost always know which default you mean.
4Meaning One: The Creation Default
When you create a feature, Flagsmith asks what it should start as. That small decision is copied into every stage at once.
What you decide at creation
When creating a feature in a Project, you give it a name and a description, and you typically choose whether it should be enabled or not by default, and, for features that carry a value, what that starting value is. Because a feature’s definition is shared across the whole Project, Flagsmith needs to put a state into every Environment, and by default it uses what you entered on the creation form.
The effect on every Environment
If you create a feature and choose to enable it by default, then Development, Staging and Production can all receive the feature switched on. That may be exactly what you want for a harmless setting. It is a serious problem for a new, untested checkout page, because the moment the feature is created, real customers in Production could see it.
graph TD
FORM["Creation form: enabled by default = yes, value = 20"] --> DEV["Development: enabled, value 20"]
FORM --> STG["Staging: enabled, value 20"]
FORM --> PRD["Production: enabled, value 20"]
A safety setting at the Project level
Because this behaviour can surprise people, many versions of Flagsmith offer a Project setting, often described as preventing flag defaults. When it is switched on, the starting state and value entered at creation are not spread across all Environments, which keeps new features switched off in places where nobody chose otherwise. The exact wording and availability may differ in your version, so open your Project settings and read the description there before relying on it. If it exists in your version, switching it on is one of the quickest safety wins in the whole product.
Imagine a chain of shops that decides its new seasonal menu with one form sent to every branch. If the form says “start selling today”, every branch starts at once, including the one whose staff have not been trained. A careful head office writes “available from the date each branch confirms”, so the decision stays local. The Project safety setting does the same for new flags.
Create new release flags disabled. Enable them first in Development, then Staging, and only then in Production, one deliberate click at a time. Creation should never be the same event as release.
A short story of a creation default gone wrong
Imagine an engineer creating a flag for an unfinished loyalty page. In a hurry, they tick the option to enable it by default. Because the feature definition is shared by every Environment, Production receives the flag in the enabled state a moment later. The page code is deployed and waiting, so real customers suddenly see half a page. Nothing was “flipped” in Production by any person. The creation form did it. Stories like this are why many teams treat creation as a safe, boring event, and keep every real decision for the later, deliberate step of enabling the flag in each Environment.
5Meaning Two: The Environment Default
This is the default most people mean in daily work: the baseline answer a feature gives inside one Environment.
What it is
Inside each Environment, every feature has a feature state: whether it is enabled, and, if it carries one, its value. That state is the Environment default. It is the answer given to anyone who does not match a segment override or an identity override. Think of it as the general rule for that stage, with overrides as the exceptions.
Why it is the most important default
For most users, the Environment default is the answer. If only staff and a pilot group have overrides, then everyone else, perhaps ninety-nine percent of customers, simply gets the Environment default. Changing it changes the experience of nearly everybody at once. That is why it deserves the strongest protection in Production.
| Rollout stage | Environment default | Overrides | Who sees the feature |
|---|---|---|---|
| Hidden | Off | None | Nobody |
| Staff trial | Off | Staff segment on | Employees only |
| Ten percent | Off | Staff and ten percent segments on | Employees and a small slice of customers |
| Full release | On | None needed | Everyone |
Notice the shape of a classic rollout: the Environment default stays off while overrides grow the audience, and the very last step is to change the default itself to on. Because that last step affects everyone, it is the one to take most carefully and to announce in your team channel.
A school has a general rule that phones stay in lockers. The rule is the Environment default. A teacher may allow phones for a project, and a doctor’s note may allow one pupil a phone for health reasons. These are overrides. Changing the general rule changes life for every pupil at once, so it is the decision the head teacher takes most seriously.
The value half of the default
For features that carry a value, the Environment default includes that value. A search feature may be enabled with the value “twenty” in Production and “five” in Development, so test runs stay small and quick. Each Environment keeps its own copy, so changing the value in one never touches another.
Because Environments hold separate copies, they can drift apart. Before every launch, compare Staging and Production side by side. A default that differs where you did not intend is a bug waiting for a busy day.
Reading defaults in the dashboard
In the feature list, each row typically shows the current state for the Environment you are looking at, along with a hint when overrides exist. Make it a habit to open the same feature in two Environments side by side, and compare the state and the value. If you only ever look at one Environment, drift can grow unseen. A good time for the comparison is the day before a launch, and again straight after any incident in which values were changed by hand.
6Meaning Three: Defaults for Values and Remote Configuration
A flag can carry more than yes or no. When it carries a number or a piece of text, the question of a good default becomes richer.
What is a value?
A value is information attached to a feature, such as a whole number, a piece of text or a true or false answer. Using values lets teams change settings of a running application without releasing new code. This is called remote configuration. Examples include the number of results on a page, the text of a banner, or the maximum size of an upload.
An empty value is also a value
A feature may have no value at all. Your code must handle that case sensibly. An application that expects a number and receives nothing might treat the missing number as zero, and zero can mean “show no results”, “allow no uploads” or, in some designs, “no limit at all”. The meaning of zero and of empty is one of the most common sources of surprise, which is why the next chapters spend time on it.
| Type of value | Example | Risky default | Safer default |
|---|---|---|---|
| Whole number, a limit | Maximum results per page | Zero, which may show nothing | The long-standing normal number, such as twenty |
| Whole number, a time | Seconds to wait for a partner service | Zero, which may mean never wait | A sensible timeout such as five seconds |
| Text, a message | Banner wording | Empty text, which shows a blank bar | No banner at all, or a neutral standard message |
| Text, a choice | Name of a payment provider | Empty, which may crash a lookup | The current trusted provider |
| True or false | Allow guests to check out | True by accident | The current business rule |
A thermostat that loses its setting should return to a comfortable temperature, not to zero degrees and not to the maximum. A good default value for a number is the one that was already working before the flag existed.
Scenario: tuning a search page during a sale
An online retailer stores the number of search results as a remote configuration value, normally twenty. During a sale peak, the team lowers it to twelve in Production. In the application code, the default for this number is twenty, the long-standing normal. If Flagsmith were unreachable during the sale, the page would show twenty results, which is slower but safe, rather than showing zero or crashing. Writing the proven number in code is cheap insurance.
7Meaning Four: The Default in Your Own Code
This is the default that protects you on the worst day. It lives outside Flagsmith, in the application that asks the question.
What it is
When an application asks the SDK for a flag, three outcomes are possible. The SDK returns an answer. The SDK returns a built-in “nothing found” answer. Or the call fails. For the second and third outcomes, the application needs its own plan. The default in code, also called the fallback or safe default, is that plan. It is written by the developers and shipped inside the application.
How SDKs help
Most Flagsmith SDKs return a harmless built-in answer when a flag is missing or Flagsmith cannot be reached, typically “not enabled” for a flag and “no value” for a setting. Many SDKs also let you supply your own default flag handler, which is a small piece of logic that decides what to return in such cases, flag by flag. The exact behaviour differs between languages and versions, so read the notes for the SDK you use. The principle never changes: never leave this to chance.
The app asks for a flag
The code asks the SDK whether a feature is enabled, or what its value is.
The SDK tries to answer
It uses fresh data, cached data or a local copy of the rules, depending on its mode.
If it cannot, the default applies
Either the SDK’s built-in answer or your own handler supplies the value.
The code carries on
The application follows the default path, and the user sees a calm, known behaviour.
A pilot flying without a working weather report does not guess wildly. The airline has a standing procedure for exactly that case, written in advance and trained for. The default in code is that standing procedure for your application.
When the default is used, nothing visibly breaks. The feature simply behaves as the default says. That silence is exactly why a wrong default can run unnoticed for days. Chapter 25 shows how to make default use visible.
Where to place defaults in the code
Resist the temptation to scatter defaults wherever a flag is used. A tidy approach is to collect every flag name and its default in one small section, often called a flag catalogue. The rest of the code asks the catalogue for a flag and receives both the live answer and, if needed, the fallback. This brings three advantages: names are written only once, a reviewer sees any default change in one place, and the unreachable test can exercise every default by switching the catalogue to fallback mode.
8Defaults in Split Features: The Control Value
When a feature splits users between versions, the word default takes a slightly different shape.
What is a multivariate feature?
A multivariate feature offers several possible values and divides users between them by percentage. It is the base of experiments. A button might say “Buy now” for some people, “Get it today” for others and “Add to basket” for the rest. Each alternative is called a variation.
The control
The original value of the feature is called the control. It is the version that people receive when they are not placed in any variation. Each variation is given a percentage of users, and whatever percentage remains unassigned falls back to the control. If two variations take twenty percent each, the control serves the remaining sixty percent. In this sense, the control is the default of an experiment.
| Group | Button text | Share of users | Role |
|---|---|---|---|
| Control | Buy now | 60 percent | The default, and the comparison point |
| Variation A | Get it today | 20 percent | First challenger |
| Variation B | Add to basket | 20 percent | Second challenger |
A bakery tests two new loaves on a few customers each morning, while most customers still get the usual loaf. The usual loaf is the control. It stays the default, so a failed experiment never leaves anyone hungry, and it also gives the baker something fair to compare against.
Why a good control matters
If the control is the long-standing, well tested value, then an experiment that goes wrong harms only the small share placed in a variation. If the control itself is something untested, there is no safe place to retreat to. Always keep the proven version as the control, and move it only after a challenger has clearly won.
At the end of an experiment, make the winning value the new control, set the variations to zero, and then remove the experiment feature from your code. Leaving old variations behind creates confusion about which value is really the default.
Pitfalls with the control
Two mistakes recur. The first is editing the control value in the middle of an experiment. Everyone in the control group suddenly receives something different, and the comparison with the variations is spoilt. Decide the control before the experiment begins and leave it alone. The second is forgetting that the control also serves anyone left unassigned. If the variations take only ten percent between them, ninety percent of users, including all anonymous visitors, receive the control, so it must be an experience you are happy for most people to have.
9The Evaluation Order, with Defaults in Place
When several rules could apply, Flagsmith has a clear order. Knowing exactly where the default sits in that order removes most guesswork.
For one feature, in one Environment, for one person, Flagsmith works from the most specific rule to the most general. It checks for an identity override first, which is a rule for one exact person. Next it checks segment overrides, which are rules for groups, taking the highest ranked one that matches. If neither applies, the answer is the Environment default. Only if the application receives no answer does the default in code take over.
flowchart TD
START["Question: value of feature X for person Y in Environment E"] --> Q1{"Identity override for Y?"}
Q1 -- Yes --> R1["Use identity override"]
Q1 -- No --> Q2{"Segment override that matches Y?"}
Q2 -- Yes --> R2["Use highest ranked matching segment"]
Q2 -- No --> R3["Use the Environment default"]
R1 --> OUT["Answer returned"]
R2 --> OUT
R3 --> OUT
OUT --> Q3{"Did the app receive it?"}
Q3 -- No --> R4["Use the default in code"]
Q3 -- Yes --> DONE["Use the answer"]
| Shopper | Identity override | Segments matched | Environment default | Answer |
|---|---|---|---|---|
| Asha, staff | None | Staff, enabled | Off | On, from the segment |
| Ben, ordinary customer | None | None | Off | Off, from the Environment default |
| Chloe, a new visitor with no account | None | None possible | Off | Off, from the Environment default |
| Dev, staff with a known issue | Disabled | Staff, enabled | Off | Off, from the identity override |
A library has a general loan period of three weeks. A student with a project gets six weeks, which is a group rule. A pupil with a doctor’s note gets twelve, which is a personal rule. The three weeks is what everyone else gets, and it is also what the librarian uses when the record of exceptions is lost.
A debugging ladder for a surprising answer
When a person sees an answer nobody expected, walk down the same ladder Flagsmith does. Do it in order, and write the finding at each step.
- Which Environment was asked? Confirm the key belongs to the stage you think it does.
- Was an identity sent? If not, only the Environment default can apply.
- Is there an identity override? Look at the person’s page in the dashboard.
- Which segments match? Check traits and their exact format, then the order of the segments.
- What is the Environment default? Compare it with the answer received.
- Did the answer arrive at all? If the answer matches none of the above, the application may have used its own default.
10Defaults for Anonymous Visitors and Missing Information
Many answers depend on who the person is. What happens when you do not know?
Identities and traits
An identity is Flagsmith’s name for one end user, usually represented by a user ID. A trait is a fact attached to an identity, such as “plan equals premium” or “country equals India”. A segment selects identities by their traits or by a percentage. These need information about the person to work.
When the person is unknown
A visitor who has not signed in has no user ID. If the application asks for the Environment’s flags without an identity, no segment rule can match, and the visitor receives the Environment default. The same happens if the application asks with an identity but never sends the trait a segment needs. A segment for “country equals Germany” simply cannot match a person whose country was never reported.
| Situation | What Flagsmith can do | Who receives the answer | Design advice |
|---|---|---|---|
| No identity sent at all | Answer from the Environment default only | Every anonymous visitor alike | Make the default a safe general experience |
| Identity sent, no traits | Apply identity overrides and percentage segments | Users who match, otherwise the default | Send traits that segments depend on |
| Trait sent in a different format | The segment may not match | The person falls to the default | Agree on one clean format for each trait |
| Identity created but data not yet loaded | Only the default is available | The person for a moment | Do not show a half loaded personalised page |
A cinema offers student discounts to anyone who shows a student card. A person who forgets the card is not turned away, they simply pay the standard price. The standard price is the default for anyone whose special status cannot be shown.
If every “premium only” feature has a default of off, then a bug that stops traits from being sent will silently remove premium features from paying customers. Monitor how many people fall through to the default, so such a bug is noticed by you before a customer notices it.
The moment a visitor signs in
A person often starts as an anonymous visitor and becomes a known user partway through a visit. Before sign-in, they receive the Environment default. After sign-in, segments and overrides may change some answers. If a feature suddenly switches on or off the moment someone logs in, the screen may jump in a way that feels strange. Plan for this by keeping the pre-login experience simple, and by refreshing flags once, calmly, straight after sign-in rather than letting values change in the middle of a task.
11How to Choose a Good Default: Five Questions
There is no universal answer, such as “always off”. There is a short method that works for any flag.
What does the old behaviour look like?
For most new features the proven choice is the world as it was before the flag. Start there.
Which failure is worse?
Compare the harm of showing the feature wrongly with the harm of hiding it wrongly. Pick the smaller harm.
Could the default cost money or trust?
Anything involving payments, personal data or promises to customers needs special care.
Does the feature protect the system?
If the flag guards against overload, losing the protection may be worse than losing the feature.
Can I live with it for an hour?
If the default stayed in place for sixty minutes, would the business cope? If not, think again.
| Flag | Worse failure | Therefore the default is |
|---|---|---|
| New payment sheet | Customers cannot pay with an untested screen | Off, using the old proven sheet |
| Fraud check on large orders | Fraud passes while the check is missing | On, because losing the protection is worse |
| Premium export tool | A non-paying customer gets a paid tool by accident | Off, because nobody should gain access by accident |
| Maintenance banner | A confusing banner appears with no real maintenance | Off, no banner |
| Heavy recommendation panel | Pages slow down in a traffic peak | Depends on whether protection or experience matters more, decided in advance |
When a traffic light breaks, drivers treat the junction as a four way stop. Nobody voted on this during the emergency. The rule says: when you cannot trust the signal, slow down and take turns. A good default is a four way stop for your feature.
Write the reasoning in the description
A default is only half a decision without its reason. Put one sentence in each flag’s description, so that the next person understands without asking. Useful descriptions read like this: “Off by default, because the old payment sheet is proven and failing back to it is harmless.” Or: “On by default, because losing this check during an outage would let large fraudulent transfers through.” Descriptions like these also teach new engineers how the team thinks, and they are far more helpful than “controls the new thing”.
12Fail-Safe or Fail-Open? Matching the Default to the Purpose
Two famous phrases from engineering describe opposite leanings. Both are correct, in different situations.
Fail-safe and fail-open
A system that is fail-closed (also called fail-secure) stops or denies when something goes wrong. A bank vault door stays shut if the power fails. A system that is fail-open allows or continues when something goes wrong. A fire exit door swings open if the power fails, because trapping people is worse than letting someone through. Which is right depends entirely on what the danger is.
Protecting access
Premium tools, admin screens and anything revealing private data. If unsure, do not show.
Unfinished features
Release flags for work that is not tested. If unsure, keep the old behaviour.
Protecting the system
Rate limits, fraud checks and safety guards. If unsure, keep the protection running.
Core journeys
Signing in and paying. If unsure, keep the proven path working so people are not blocked.
Notice that “off” is not always the safe answer. A flag that enables a protection is safest when its default is on. A flag that enables a risky new behaviour is safest when its default is off. The skill is to ask, for each flag, which direction protects people and the business.
A hospital’s medicine cupboard locks when the power fails, to keep drugs safe. The same hospital’s emergency exits unlock when the power fails, to let people out. Same building, same power failure, opposite defaults, and both are right.
Scenario: a safety guard on large payments
A payments company has a boolean flag that enables an extra identity check on very large transfers. During a platform incident, Flagsmith is unreachable for several minutes. Because the code default for this flag is “on”, the check keeps running and fraud attempts are blocked. If the default had been “off” by habit, the company would have briefly lost protection at a time when attackers watch for exactly such moments.
When the answer is mixed
Some flags guard behaviour where both directions carry a cost. A recommendation panel may slow the site if it runs during a traffic peak, yet hiding it may cost sales. In such cases, decide in advance what matters most for the situation in which the default will be used, and note it. If the default is used because Flagsmith is unreachable, that is usually a moment of general trouble, and lighter behaviour tends to be wiser. Writing “when in trouble, lighter is better” in the description gives future engineers a rule they can apply to similar flags.
13Defaults by Kind of Flag
Practitioners sort flags into a handful of kinds. Each kind has a natural default, which saves thinking from scratch every time.
The kinds, briefly
Release flags hide unfinished work and are short lived. Experiment flags compare versions with real users. Operational flags let engineers change system behaviour under stress. Kill switches turn a risky feature off in an emergency. Permission flags give certain customers or staff special access. This classification has been popularised by engineers writing on well known software design sites.
| Kind | Creation default | Default in code | Why |
|---|---|---|---|
| Release flag | Off | Off | Unfinished work must stay hidden until released on purpose |
| Experiment flag | Off, with the control as the value | The control value | The proven version is the fair comparison and the safe fallback |
| Operational flag | Off, until tuning is needed | The normal, healthy behaviour | Tuning is for emergencies, not for everyday life |
| Kill switch | On, meaning the feature runs | Usually on | The feature is meant to run, and the switch exists to stop it |
| Permission flag | Off | Off | Nobody should gain a capability by accident |
The table gives you a first guess, not a law. Run the five questions from Chapter 11 when a flag is unusual, such as a kill switch that guards something where “on” is risky, and write the reasoning in the description.
A kitchen has different safe settings for different tools. The oven is switched off by default when you leave. The fridge is left on by default when you leave. Nobody has to think about it each time, because each appliance has a natural resting state. Flag kinds have natural resting states too.
14Defaults for Numbers and Text: The Zero Trap and Others
Values look simple, yet they hide the most surprising default bugs. A little discipline in code prevents nearly all of them.
The zero trap
When a number is missing, many programming languages quietly treat it as zero. Zero might be harmless, or it might change meaning completely. A “maximum items in basket” of zero could mean customers cannot buy anything. A “retry limit” of zero could mean never try again. A “timeout” of zero could mean wait forever. The same quiet zero can be a disaster in one place and invisible in another.
Units matter
A value of “five” is meaningless without a unit. Is that five seconds, five minutes or five hundred milliseconds? If one team writes the value thinking in seconds and the code reads it as milliseconds, the feature misbehaves in a way that looks like a mystery. Put the unit in the feature’s name and description, for example “partner_timeout_seconds”, so nobody has to guess.
Defend your code
Treat every value that comes from Flagsmith the same way you would treat input from a stranger. Check that it exists, check that it is the type you expect, and check that it lies within a sensible range. If it fails any check, use the default in code. This habit is sometimes called clamping: forcing a value to stay between a lowest and highest acceptable number.
| Setting | Sensible range | If the value is outside the range | Reason |
|---|---|---|---|
| Results per page | 5 to 50 | Use 20 | A typo of 5000 would crash the page |
| Partner timeout in seconds | 1 to 30 | Use 5 | Zero or very large values cause hangs |
| Retry attempts | 0 to 5 | Use 3 | Too many retries can flood a struggling partner |
| Banner message length | 0 to 140 characters | Show no banner | A pasted essay would wreck the layout |
A shower has a safety stop on the hot tap, so that however far you turn it, the water never scalds. Even if someone fits the wrong handle, the stop holds. Clamping is the safety stop for numbers that arrive from outside.
Flag values can be edited by humans in a dashboard, and humans make typos. A dashboard value is not a trusted source until your code has checked it.
True and false stored as values
A feature can carry a value that is itself the text “true” or “false”, or a true and false type. This is a different thing from the enabled state of the feature. A feature may be enabled with a value of false, which the code must read as “feature on, setting off”. When values and states disagree, a missing value could be read either way, depending on the language. If you need a yes or no answer, use the enabled state, and keep values for numbers and text. If you must store a boolean value, give the default in code explicitly and name the feature so the meaning is obvious.
15When Exactly Is the Default Used? A Catalogue of Cases
It helps to list every situation in which a default takes over, so none comes as a surprise.
| Situation | Which default is used | Visible to the user? | How to stay safe |
|---|---|---|---|
| Person matches no override | Environment default | Yes, it is their normal experience | Make the Environment default a good general answer |
| No identity supplied | Environment default | Yes | Design for anonymous visitors |
| Required trait never sent | Environment default | Yes, often unnoticed | Monitor trait delivery |
| Flagsmith unreachable at app start | Default in code | Usually yes | Test the app with no connection |
| Flagsmith unreachable later | Last known values, or default in code | Often not | Know how your SDK caches |
| Flag name does not exist | Default in code | Quietly | Share flag names in one place and review changes |
| Flag deleted, code remains | Default in code | Quietly | Remove code before deleting the flag |
| Wrong Environment key used | The other Environment’s default | Yes, but confusing | Keep keys separate and clearly named |
| Value of the wrong type | Default in code, if the app checks | Depends | Validate every value |
Notice that some defaults are part of normal life, such as the Environment default for ordinary users, while others are emergency measures, such as the default in code. Both deserve care, but the second kind deserves it before the emergency, because there will be no time to think during one.
A house has a spare key under a flowerpot, a neighbour with another, and a locksmith’s number on the fridge. Each is a fallback for a different failure, and none helps unless it was arranged before you were locked out.
16Defaults, Caching and the Last Known Value
Between a fresh answer and a default sits a third possibility that is often better than either: the last answer you remember.
Fresh, remembered, or default
Most SDKs keep a copy of the flags they last received, either in memory or, for mobile and browser apps, in local storage on the device. If a later request fails, a well designed SDK can carry on with the last known values instead of falling all the way back to the default in code. This is usually a better experience, because the last known values were chosen by a person and reflected the real state of the business a moment ago.
flowchart TD
A["App needs flag value"] --> B{"Can SDK fetch fresh values?"}
B -- Yes --> C["Use fresh value"]
B -- No --> D{"Does SDK hold earlier values?"}
D -- Yes --> E["Use last known value"]
D -- No --> F["Use default in code"]
Why this matters for the default you choose
The default in code is used only when the first two options fail. That happens most often when an application starts for the very first time with no connection, or when its stored copy has been cleared. Because those moments are rare but serious, the default should still be chosen with care, even if you expect to use it seldom.
| Moment | Fresh values? | Last known values? | Result |
|---|---|---|---|
| Normal running | Yes | Yes | Fresh values |
| Short network blip | No | Yes | Last known values |
| First ever start, no network | No | No | Default in code |
| App data cleared by the user | Maybe | No | Fresh if reachable, otherwise default |
| Server restarting with no copy | No | No | Default in code until it reconnects |
If you cannot reach a friend to ask which restaurant to meet at, you first try remembering what you agreed yesterday. Only if you remember nothing do you fall back on the habit of meeting at the usual cafe. Fresh answer, remembered answer, usual habit: the same ladder.
Whether and how an SDK keeps last known values depends on the language, the mode and the options chosen. Read the documentation for the SDK you use, and test it by switching the network off on purpose.
How old is too old?
Last known values are helpful, but they do age. A value remembered from an hour ago is almost always still right. A value remembered from last week might not be, especially if a kill switch has been flipped since. Teams usually set a maximum age for stored values, after which the application prefers its coded default to a stale memory, or tries harder to refresh. The right age depends on how quickly your flags change and how much harm a stale value could do. For flags that guard safety, shorter is wiser.
17Defaults When You Create or Clone an Environment
Environments are born with defaults too, and the way they are created affects everything that follows.
A new Environment starts somewhere
When you add an Environment to a Project, it needs a state for every existing feature. Depending on how it is created, that state may come from a basic blank starting point, or from a copy of another Environment. Flagsmith lets you create a new Environment by cloning an existing one, which copies its states and values. This is the quickest way to start a new Staging or regional Environment from a known good set of values.
Decide the source
Choose which Environment is the best model for the new one. Often it is Staging, not Production, so no live exceptions are copied.
Create by cloning
The new Environment receives the same feature states and values as the source at that moment.
Review the copied defaults
Read through the list. Some values, such as partner addresses or limits, may need to differ in the new stage.
Give it its own keys
Every Environment has its own Environment keys. Use the new keys only in the applications for that stage.
Drift: the slow divergence
Once separate, Environments drift. Someone changes a value in Production during an incident and forgets to match Staging. Weeks later a test passes in Staging and fails in Production, because their defaults are no longer alike. Regular side by side comparison, especially before launches, catches drift early.
A chain opens a new branch by copying the layout and procedures of a well run existing branch. Over the years each branch makes small local changes. Unless head office occasionally compares them, no one can say which differences were deliberate and which were accidents.
Cloning Production copies its live settings, including special overrides for real customers. Make sure you understand what is being copied before putting those rules into a test stage that other people can freely change.
Regional Environments and local defaults
Some products add an Environment for a particular region, for example one for a country with different laws or payment methods. Its defaults are likely to differ from the global Production Environment, and that is fine, provided the differences are deliberate and written down. A short table listing which values differ between a regional Environment and Production, and why, saves the next engineer from “fixing” a difference that was important.
18The Silent Default: Typos, Deleted Flags and Mismatched Names
The most irritating bugs around defaults are the ones where nothing visibly goes wrong. The default simply keeps being used.
How silent defaults happen
A flag lookup is made by name. If the name in code does not exactly match the name in Flagsmith, the lookup finds nothing, and the default quietly takes over. This can happen through a simple typo, a difference in capital letters, an extra space, a rename in the dashboard, or a deletion. The code does not crash, because defaults are designed to avoid crashes. The feature just never turns on, and engineers lose hours wondering why a flag that is clearly enabled has no effect.
| Cause | What Flagsmith shows | What the app does | Cure |
|---|---|---|---|
| Typo in the flag name in code | Flag enabled | Uses default, feature never appears | Keep names in one shared list in the code |
| Different capital letters | Flag enabled | Uses default | Agree one style and enforce it |
| Flag renamed in the dashboard | Flag under a new name | Old name no longer found | Never rename, create a new flag instead |
| Flag deleted too early | No such flag | Uses default | Remove code first, then delete the flag |
| Test build using the wrong Environment key | Flag enabled in another Environment | Reads that Environment’s state | Name keys clearly and keep them separate |
Making silent defaults loud
The best protection is to turn silence into a signal. When the application asks for a flag that exists in its shared list but receives the default because the flag was not found, write a log message or increase a counter. A graph of “defaults used” that suddenly rises tells you that names or connections are broken long before customers complain.
If you post a letter to a wrong address, no alarm sounds. It simply never arrives, and you only find out when someone asks why they heard nothing. A tracking number turns that silence into information. A counter of “defaults used” is the tracking number for flags.
19Rollout Patterns Shaped by the Default
The same audience can be reached in two opposite ways, depending on which side the default is placed. Each has a natural use.
Pattern A: default off, exceptions on
The Environment default is off, and chosen groups are switched on through segment overrides. This is the classic rollout. The feature starts invisible, staff see it first, a pilot group next, a percentage after that, and finally the default itself is switched on. It is the safest pattern for new features, because anything not mentioned is unaffected.
Pattern B: default on, exceptions off
The Environment default is on, and chosen groups are switched off. This suits a feature that is already live for everyone, where you need to hold it back from a few people, for example customers in a country where a law forbids it, or a partner with an older integration that cannot cope. It also suits the “kill for one group” case: leave the feature on for most, and quickly switch it off for the one segment where a problem appears.
flowchart LR
subgraph PA["Pattern A: default off"]
A1["Environment default: Off"] --> A2["Staff segment: On"]
A1 --> A3["Ten percent segment: On"]
A1 --> A4["Everyone else: Off"]
end
subgraph PB["Pattern B: default on"]
B1["Environment default: On"] --> B2["Restricted country segment: Off"]
B1 --> B3["Legacy partner segment: Off"]
B1 --> B4["Everyone else: On"]
end
| Question | Pattern A: default off | Pattern B: default on |
|---|---|---|
| Best for | Releasing a new feature | Excluding a few groups from a live feature |
| Unknown people receive | The feature is hidden | The feature is shown |
| Risk if a trait is missing | People miss out on the feature | People who should be excluded may see it |
| Danger to watch | Forgetting to widen the audience | A missing exclusion rule exposing the feature wrongly |
A club can have a guest list, where only named people enter, or a banned list, where everyone enters except named people. A guest list is safer for a private party. A banned list suits a public venue. The choice depends on what happens to an unknown person at the door.
Pattern B depends on exclusion rules matching correctly. If a person’s country trait never arrives, they fall to the default, which is on, even if they should have been excluded. When legal or contractual exclusions are involved, prefer a design where missing information leads to the safe outcome.
Moving from Pattern A to Pattern B
Many features travel through both patterns in their lifetime. They begin as Pattern A, with the default off and groups added. When the feature reaches everyone, the default is switched on, and the remaining overrides are removed. Later, if a particular group must be excluded, a segment override for that group is turned off, which is Pattern B. At each hand-over, check that no old override is left behind pointing the wrong way. A stray “on” override for staff is harmless once the default is on, but a stray “off” override can quietly hide the feature from a group for months.
20Defaults and Percentage Rollouts
A percentage rollout gives different answers to different people at the same time. The default plays a quiet but important role.
How the default and the percentage work together
A percentage segment selects a share of identities, such as ten percent of all users. A segment override then gives those people a different answer from the default. Everyone outside the percentage receives the Environment default. So at “ten percent”, ninety percent of users are, in effect, served by the default. This is why the default must be a good experience in its own right, because it is the experience of the large majority during most of a rollout.
Steady groups
The split is steady for each identity. Flagsmith works out a position for each person from their identity, so the same person stays in the same group as the percentage widens. Someone in the first ten percent remains included at twenty-five percent. No person flickers between two experiences. This steadiness only works for people with an identity. An anonymous visitor with no identity cannot be placed in a percentage and therefore always receives the default.
Canary
A tiny audience proves the feature does not crash. Ninety-nine percent receive the default.
Early slice
Enough users to notice patterns. The default still serves nine in ten people.
Half and half
The new path carries serious load. The default is now half of all experience.
Switch the default
The final step is to set the Environment default to the new behaviour and retire the segment.
A new bus route is first run on one morning in ten, while the old route serves the rest. For most of the trial, the old route is what most people experience, so it must stay reliable. Only when the new route proves itself does the old one retire.
21Managing Defaults at Scale: The Register
With ten flags, you can remember every default. With a thousand, you need a system.
Keep names and defaults in one place in code
Instead of scattering flag names and their default values across many files, collect them in one shared section of the code. Each entry states the flag name and the default for it. A developer who needs a flag finds it there, and a reviewer sees any change to a default at a glance. This also protects against typos, because a name is written once.
Keep a human register too
In your team’s documents, keep a short table listing each important flag, its kind, its default in code, the reason for that default and its owner.
| Flag | Kind | Default in code | Reason | Owner |
|---|---|---|---|---|
| checkout_new_payment_sheet | Release | Off | Old sheet is proven | Store team |
| search_results_per_page | Value | 20 | Long-standing normal | Search team |
| payments_enable_large_transfer_check | Protection | On | Losing the check is worse | Payments team |
| reports_enable_advanced_export | Permission | Off | No accidental access | Reports team |
Review defaults when code changes
Whenever a pull request adds a flag or changes a default, make it a standing question in the review: what happens if the answer never arrives? A reviewer who asks this one question prevents a surprising number of incidents.
No flag enters the codebase without a written default and a one line reason. If the author cannot explain the default in a sentence, the default has not been chosen yet.
A checklist for code review
- Is the flag name taken from the shared catalogue, not typed by hand?
- Is there an explicit default, and does it lean towards the smaller harm?
- Is the reason for the default written in the flag’s description?
- If the flag carries a number or text, is the value checked for type and range?
- Is there a test with the flag on, off, and with no answer?
- Does the default agree with the Environment default, or is the difference explained?
22Testing Your Defaults
A default that has never been exercised is a guess. Testing turns it into a promise.
The unreachable test
The most valuable test is also the simplest: run the application, in a test setting, with Flagsmith deliberately unreachable. Start it with no connection, with a wrong key, or with the network blocked, and watch what happens. Every important screen should still work, using its defaults. If something breaks, you have found a missing or careless default while the stakes are small.
The three states of every flag
For each flag, test three situations. With the flag on, the new behaviour works. With the flag off, the old behaviour works. With no answer at all, the default works. Most teams remember the first two and forget the third, which is exactly the situation the default exists for.
| Test | How to set it up | What to check |
|---|---|---|
| Flag on | Enable in Staging for the test user | New behaviour appears and works end to end |
| Flag off | Disable in Staging | Old behaviour appears and nothing is broken |
| No answer, first start | Run the app with the network blocked and no stored copy | Default behaviour appears, no errors on screen |
| No answer, later | Block the network after a successful start | Last known values are used, app stays calm |
| Missing flag | Ask for a name that does not exist in the test Environment | Default behaviour appears, and a warning is logged |
| Bad value | Temporarily set a nonsense value in Staging | The app rejects it and uses the default |
A building holds fire drills, not because anyone expects a fire, but because an untested exit plan is only a hope. Switching off the network in a test is your fire drill.
Provide a small helper in your test code that lets a test choose a flag’s state, or choose “no answer”, without calling Flagsmith at all. Fast tests that do not depend on the network are tests people actually run.
23Who May Change a Default? Permissions and Change Control
Changing an Environment default in Production is among the most powerful actions in Flagsmith, because it affects everyone not covered by a special rule.
Why it needs care
An override changes the experience of a chosen group. The Environment default changes the experience of everybody else, which is usually most of your users. Flipping it in Production is therefore the equivalent of a release to the whole population, and should be treated with the same seriousness as deploying code.
Layers of permission
Flagsmith controls access at the Organisation, Project and Environment levels. Creating features, and thereby setting the creation default, is a Project-level permission. Changing an Environment’s feature state, which sets the Environment default, is an Environment-level permission. Give the first more widely, and the second only to a small, trained group for Production. Where your plan offers change requests, require a second person’s approval before a Production default changes, so that one slip cannot affect every customer.
| Action | Level | Typical group | Care needed |
|---|---|---|---|
| Create a feature with a creation default | Project | Product engineers | Moderate, because it can spread to Environments |
| Change a default in Development | Environment | Product engineers | Low |
| Change a default in Staging | Environment | Engineers and testers | Moderate |
| Change a default in Production | Environment | Release group | High, ideally with approval and a note in chat |
| Change the default in code | Code repository | Developers through review | High, as it needs a release and rarely changes |
Changing the house special on a restaurant’s printed menu needs the owner. Changing tonight’s special on the blackboard can be done by the head chef. The more people a change affects and the longer it lasts, the higher the decision goes.
Exact permission names, approval flows and scheduled changes depend on your version and plan. Treat the principles as stable, and confirm specifics in your dashboard before writing a policy.
24Security Thinking About Defaults
Defaults are decisions about what happens by accident. That makes them a security topic.
Permissive defaults are a risk
A default that grants access, for example enabling a premium tool when no information is available, is a standing invitation for mistakes to become leaks. The principle of fail-safe defaults says the opposite: when in doubt, deny, unless denial itself is dangerous. For flags that gate capabilities, choose defaults that give nothing away.
Defaults are visible to clients
Anything sent to a browser or phone can, in principle, be read by the user. That includes flag names and values. Do not put secrets, internal code names or private comments in values or descriptions that clients can read. Where your version offers the option, hide disabled flags from client applications, so people cannot discover the names of unannounced features.
A flag is not a lock
A flag decides what the interface shows. It does not protect the data behind it. Anything that really must be protected needs a permission check on your own servers, whatever the flag or its default says. A default of “off” that hides a button does not stop a determined person from calling the underlying service directly.
Client-side key
Belongs to one Environment, is safe in websites and apps, and can only read flag values.
Server-side key
Belongs to one Environment and must stay on your servers. It unlocks richer access, such as local evaluation.
Organisation key
Lives above the Project and manages Flagsmith itself. Never place it in an application.
A “staff only” sign on a door guides honest visitors. It does not stop a thief. For that you need a real lock and a key. A default and a flag are the sign, and your server checks are the lock.
Do not store personal data in values
Because values travel to client applications, never place personal data, private email addresses or customer lists inside a flag value or a trait you do not need. A value should be a small setting, not a record. If you must target by a personal fact, send a minimal derived trait, such as a plan name or a region, rather than the raw data, and follow your company’s rules on privacy.
25Monitoring: Seeing When Defaults Are Being Used
The cure for a silent default is to make it speak.
What to measure
Three simple measures give real insight. The default usage count is how often the application fell back to a default in code, per flag. The missing flag count is how often it asked for a flag that does not exist. The fetch failure count is how often it failed to reach Flagsmith at all. In a healthy system all three are close to zero, and any sudden rise deserves a look.
Putting it on a graph
Send these counts to the monitoring tool your team already uses, such as Datadog, and place flag changes on the same graph by using the integration that announces them. When defaults-used jumps up right after a deployment, you know a name was mistyped. When fetch failures jump at the same time as a platform incident, you know the app is running on last-known values. The audit log of Flagsmith records who changed what and when, which completes the story.
An application is released
A new version asks for a flag by a name that has a typo.
The counter rises
The “missing flag” count for that name jumps from zero.
An alert tells the team
A simple threshold on the counter sends a message to the team channel.
The fix is small
The name is corrected in the next release, and the counter falls back to zero.
A car’s dashboard has a light that comes on when the engine is running on a backup setting. You can still drive, but you know something needs attention. A counter of defaults used is that dashboard light for your flags.
26Anti-patterns and Common Mistakes
These traps appear in almost every company that adopts feature flags. Learn them now and avoid paying for them later.
The mistake
Leaving the default in code to the SDK’s built-in answer.
Why it hurts
The SDK has no idea what is safe for your product. Its built-in answer may suit a release flag and be dangerous for a protection flag.
Do this instead
Write an explicit default for every flag, with a one line reason, and keep them together in one place in the code.
The mistake
Creating new flags enabled by default, with the creation default spreading to Production.
Why it hurts
An unfinished feature reaches real customers the instant it is created, before anyone has chosen to release it.
Do this instead
Create release flags disabled, and use the Project safety setting that prevents flag defaults from spreading, where your version offers it.
The mistake
Treating “off” as automatically safe.
Why it hurts
For a flag that enables a protection, off is the dangerous direction. A fraud check or rate limit silently disappears when the default is off.
Do this instead
Ask for each flag which failure is worse, and set the default towards the smaller harm.
The mistake
Trusting a value from the dashboard without checks.
Why it hurts
A typo such as a zero or an extra digit changes behaviour dramatically, and a human edit is far easier than a code release.
Do this instead
Validate type and range, and use the default in code when a value fails the check.
The mistake
Defaults in code that disagree with the Environment default and nobody knows why.
Why it hurts
A person flips a flag in the dashboard and expects one behaviour, but during a failure the application behaves differently, causing confusion in the middle of an incident.
Do this instead
Where they must differ, write the reason in the flag’s description, so the next engineer sees the gap and understands it.
More small mistakes worth naming
- Never testing the application with Flagsmith unreachable.
- Using zero as a quiet default for numbers that mean limits or times.
- Letting Staging and Production defaults drift apart.
- Reusing a flag name for a new purpose, so old code reads a default that no longer fits.
- Not counting how often defaults are used.
The mistake
Using the Environment default as a permanent holding place for temporary experiments.
Why it hurts
Months later nobody knows whether the current default is the winner of an experiment or a leftover from a test. A baseline that nobody can explain is a risk for every future change.
Do this instead
At the end of every experiment, make the winner the plain default, remove the variations, and write a line in the description saying so.
27Failure Scenarios and Recovery
Things will go wrong. Teams that planned their defaults recover in minutes, and teams that did not recover in hours.
Scenario one: Flagsmith is unreachable during a launch
Applications serve last known values where they have them, and defaults in code where they do not. If defaults were chosen well, customers see the old, proven behaviour and the launch simply pauses. Once the platform returns, the flags apply as planned. After the incident, review how many users fell to defaults and whether any default was wrong.
Scenario two: a feature never turned on, though the flag is enabled
Check three things in order. Is the application using the correct Environment key? Does the flag name in the code match exactly the name in Flagsmith? Has the app refreshed its values since the change? Most “it does not work” reports end at one of these. The counter of missing flags makes the second check instant.
Scenario three: a Production default was changed by mistake
Restore the previous value first, which the audit log shows. Customers come before investigation. Afterwards ask how a person with permission came to flip the wrong Environment, and consider approvals and clearer Environment names.
Scenario four: a numeric value was mistyped
A value of two thousand where twenty was meant should have been rejected by the range check in code. If it was not, correct it in the dashboard at once, then add the missing range check so the next typo is harmless.
Scenario five: premium features vanished for paying customers
Notice the rise in defaults used
The monitor shows many premium flags falling to their default of off.
Look at traits
A release changed how the plan trait is sent, so segments no longer match.
Restore the trait
Roll back or fix the sending code, so identities carry the right plan again.
Confirm and tell customers
Check a sample of paying accounts and communicate if anyone was affected.
Scenario six: a flag was deleted while code still used it
The application falls back to its default, which is why defaults matter. Recreate the flag with the same name, restore its states from the history, and plan a proper removal from code before deleting it again.
Scenario: a cautionary tale from finance
One of the best known software disasters involved the trading firm Knight Capital in 2012. In widely reported accounts, a release reused an old switch that woke long-dead code on a server that had not been updated, and the firm lost roughly four hundred million dollars in about forty-five minutes. Details have been debated, but the lessons for anyone who relies on defaults are clear: never reuse the meaning of an old flag name, make sure every server runs the same version, and remember that an old default can wake up in unexpected ways.
Write these down
Where the defaults register lives, how to find a flag’s previous value, which dashboard shows defaults used, who may change Production, and who to tell. If any answer is “I would have to search for it”, write it down today.
After any incident: three questions for the review
Once the pressure is off, hold a short, blame-free review. Ask three questions about defaults. Which defaults were actually used, and for how long? Did each one behave as the register said it would? And is there any flag where the default surprised us? Write the answers on one page, update the register, and fix any default that proved wrong. Over a year, a team that does this builds a register that is accurate because every incident has sharpened it.
28Scaling, Speed and Resilience
Defaults are also what let a flag system serve millions of users without becoming a weak link.
Do not wait forever for an answer
Any network call can be slow. If an application waits for Flagsmith before showing a page, a slow answer becomes a slow page. Good applications set a short timeout, which is a limit on how long to wait, and use the default if the answer has not arrived. A timeout of a few hundred milliseconds for a page-critical flag is common, while background refreshes can wait longer.
Start fast on a cold start
A cold start is when an application launches with nothing remembered. Mobile apps opened for the first time, and servers freshly started, are cold. During a cold start there are no last known values, so the default in code is what the first screen uses. Many teams make the first screen independent of flags where possible, and let flags refine later screens, so the cold start is quick and calm.
Cache and local evaluation
Fetching flags on every check would be slow and costly. SDKs keep flags in memory and refresh on a timer. Some server SDKs offer local evaluation, downloading the complete rule set once and deciding flags inside your own server in microseconds. In this mode the platform is not asked for each decision, so even a long outage affects only how fresh the rules are, not whether decisions can be made.
flowchart LR
U["Millions of users"] --> APPS["Your application servers"]
APPS --> SDK["SDK with local cache"]
SDK -- "periodic refresh" --> PROXY["Optional local proxy"]
PROXY -- "occasional sync" --> FS["Flagsmith platform"]
SDK -. "if nothing available" .-> DEF["Default in code"]
A city does not ask the central water plant every time someone turns a tap. Water waits in local towers, and houses are supplied even if the plant has a short problem. Caches are the towers, and the default in code is the emergency reserve tank at the bottom of each house.
Choosing timeouts for different kinds of flag
| Kind of flag | How long to wait | What to do on timeout |
|---|---|---|
| A flag that shapes the first screen | Very short, a few hundred milliseconds | Show the default screen at once |
| A flag for a later, optional panel | A little longer, around a second | Hide the panel, or show it in default form |
| A background refresh | Several seconds | Keep last known values and try again later |
| A protection flag on a critical path | Short, then lean to the protective default | Keep the protection running |
29Worked Example: Designing Defaults for an Online Store
Ideas become clear when applied. Follow the team at a fictional retailer, Northwind, as they decide every default for four flags.
The situation
Northwind sells goods through a website and a mobile app. A team of about twenty people works on both. They are preparing four flags for the coming sale season: a new payment sheet, a limit on search results, a large transfer safety check, and an advanced export tool for business customers. For each, they walk through the same questions from Chapter 11.
| Flag | Kind | Creation default | Production Environment default | Default in code | Reason |
|---|---|---|---|---|---|
| checkout_new_payment_sheet | Release | Off | Off, then segments, then on | Off | The old sheet is proven. Failing back to it is harmless |
| search_results_per_page | Value | 20 | 20, lowered to 12 on sale days | 20, with a range of 5 to 50 | Twenty is the long-standing normal. Out-of-range values are ignored |
| payments_enable_large_transfer_check | Protection | On | On | On | Losing the check is the worse failure |
| reports_enable_advanced_export | Permission | Off | Off, with premium segment on | Off | Nobody should gain a paid tool by accident |
The steps they followed
Switch on the safety setting
The Project setting that stops creation defaults spreading is enabled, so new flags never appear in Production by accident.
Write the register
The four flags and their defaults go into one table in the team’s documents, with owners.
Put defaults in code
The same four defaults are written in one shared section of the code, with a one line reason each.
Add range checks
The search value is accepted only between five and fifty, otherwise twenty is used.
Test with no connection
In Staging, the team starts the app with the network blocked and confirms every screen still works.
Add the monitor
A graph of “defaults used” is added to the dashboard the team already watches, with an alert on a sharp rise.
Rehearse a failure
During a quiet hour, the team blocks Flagsmith from a test server and watches the counters rise and the product stay calm.
The result on sale day
During the sale, a short network problem prevents some mobile apps from refreshing flags. The apps use last known values. A few brand new installs with no stored copy use the coded defaults: the old payment sheet, twenty results, the safety check on and the export tool off. Customers shop normally. The “defaults used” graph rises for twenty minutes, then falls. Engineers read the graph, confirm that all defaults behaved as designed, and write a short note. Nobody is woken at night.
A shop that has planned for a power cut has torches by the till, a manual card machine in a drawer and a sign saying “cash only for a while”. Customers hardly notice, and the staff stay calm. The coded defaults are the torches and the sign.
30Auditing the Defaults You Already Have
Few teams start from nothing. If flags already exist, a short audit can find the weak defaults before an incident does.
List every flag in use
Search the code for flag lookups, and compare with the features in the Project. Note flags that exist in only one place.
Record each default in code
For each flag, write down what happens if no answer arrives. Where the code has no explicit default, mark it in red.
Ask the five questions
For each flag, ask which failure is worse and whether the recorded default leans the right way.
Compare with Environment defaults
Check whether the default in code differs from the Production default, and whether the difference is deliberate.
Fix the worst first
Start with flags guarding money, personal data and protections. Cosmetic flags can wait.
Add tests and monitors
For each fixed flag, add the unreachable test and the defaults-used counter.
| What you find | How serious | What to do |
|---|---|---|
| No explicit default for a protection flag | High | Set the default to on today and test it |
| A release flag whose default is on | High | Check whether unfinished work is exposed, and change the default to off |
| A number with no range check | Medium | Add a sensible range and a default |
| Default in code differs from Production with no explanation | Medium | Write the reason in the description or align them |
| A flag that no code uses any more | Low, but it adds clutter | Remove it after confirming nothing reads it |
A homeowner who walks around checking that every smoke alarm has a battery is doing an audit. It takes an hour, nothing is on fire, and it is the most valuable hour of the year. Auditing defaults is the same quiet insurance.
You know the audit worked when anyone on the team can state the default of any important flag in one sentence, and give the reason for it.
Quick wins in one afternoon
If time is short, three small actions give most of the benefit. First, switch on the Project setting that stops creation defaults spreading, if your version offers it. Second, find every flag that guards money, personal data or a protection, and give each an explicit default in code. Third, add a single counter for defaults used to your monitoring tool. These three steps take hours, not weeks, and they catch the failures that hurt most.
31Advantages, Disadvantages and Trade-offs
Having several layers of default is a design choice with real benefits and real costs.
Advantages
- Releases and incidents stay calm, because every question has a planned answer.
- New features can be created safely, with no effect on customers until released.
- Layered answers let you choose the right fallback for each situation.
- Experiments have a safe control to retreat to.
- Applications remain usable when the flag platform is slow or unreachable.
- Defaults can be reviewed and tested like any other part of the design.
Disadvantages and trade-offs
- Four places hold a default, so confusion about which one applies is common.
- Defaults in code can only change with a release, so mistakes there are slow to correct.
- Defaults can hide problems, because the product keeps working while quietly using a fallback.
- Environment defaults drift apart unless someone compares them.
- A wrong default may stay unnoticed for a long time, because it only matters in rare moments.
- Defaults need documentation and discipline, which cost team time.
The central trade-off: conservative or helpful
A very conservative default, such as “hide every new thing”, is safe but may keep customers from benefits. A very helpful default, such as “show everything available”, is generous but exposes unfinished or risky behaviour. There is no single right point. The method in this guide is to choose per flag, according to which failure hurts more, and to write the reasoning down.
When defaults are not the right tool
A default is a fallback, not a business rule. If something must be true by law or contract, such as showing a required notice to customers in a certain country, relying on a flag default is fragile. Such rules belong in code or in a controlled data store with proper review. Flags and their defaults are best for behaviour that changes often and can safely fall back.
A word on teams and habits
The technical side of defaults is small. The habit side is large. A team that asks “what is the default?” in every design review and every code review will rarely be surprised. A team that never asks will be surprised repeatedly, and each surprise will feel like bad luck rather than a missing question. If you adopt only one habit from this guide, make it the single question: if the answer never arrives, what do we want to happen?
32Best Practices Checklist
A short list to keep nearby. If you do these ten things, you will avoid most of the pain described in this guide.
Say which default you mean
Creation, Environment, control value or code. Name it in every discussion.
Create flags disabled
Creation should never be the same event as release. Use the Project safety setting where available.
Write every default in code
Never leave the answer to the SDK’s built-in choice. Give each default a reason.
Ask which failure is worse
Lean towards the smaller harm. For protections, that often means on.
Validate values
Check type and range, and fall back to the default when a value is nonsense.
Keep a register
One table with flag, default, reason and owner. Update it when flags change.
Test the unreachable case
Run the app with no connection before every major release.
Make defaults visible
Count defaults used and missing flags, and alert on sudden rises.
Protect Production defaults
A small named group, approvals where available and a note in chat.
Remove old flags
Delete code first, then the flag, so no stale default is left to wake up.
Making the checklist stick
Lists on their own fade from memory. Turn the ten points into a short template that is attached to every new flag’s ticket, so each point is answered while the flag is being created rather than remembered later. Review the template twice a year, and drop any item that never changes an outcome. A checklist of six living questions beats a checklist of twenty that people tick without reading.
33Glossary: Every Term in One Place
Keep this table nearby while reading documentation or talking with your team.
| Term | Plain meaning |
|---|---|
| Default | The answer used when nothing more specific applies. |
| Creation default | The starting state and value entered when a feature is first created. |
| Environment default | The baseline state and value of a feature inside one Environment. |
| Control value | The original value of a split feature, served to users outside every variation. |
| Default in code | The fallback used by the application when no answer arrives. |
| Safe default | A default chosen because it causes the least harm if used. |
| Fail-safe default | The principle that unspecified cases should lean towards the safe outcome. |
| Fail-open | Continuing to allow or run when something goes wrong. |
| Fail-closed | Stopping or denying when something goes wrong. |
| Feature flag | A switch inside software that decides whether a behaviour is active. |
| Value | Information such as a number or text attached to a feature. |
| Remote configuration | Changing a value in a running application without a new release. |
| Multivariate feature | A feature with several values split between users by percentage. |
| Variation | One of the alternative values in a split feature. |
| Project | The home of one product’s features, segments and tags. |
| Environment | One stage, such as Development or Production, holding live states. |
| Feature state | Whether a feature is on, and its value, in one Environment. |
| Identity | An end user or account whose flags are being worked out. |
| Trait | A fact attached to an identity, such as plan or country. |
| Segment | A rule that selects a group of identities. |
| Segment override | A different answer for a segment in one Environment. |
| Identity override | A different answer for one specific identity. |
| SDK | A ready made library that lets your application talk to Flagsmith. |
| Default flag handler | SDK logic that decides what to return when a flag is missing or unreachable. |
| Last known value | The most recent answer an SDK received, kept for use when fetching fails. |
| Local evaluation | Downloading rules once and deciding flags inside your own server. |
| Cold start | Launching an application with nothing remembered. |
| Clamping | Forcing a value to stay inside a sensible range. |
| Drift | Environments gradually becoming different from each other. |
| Audit log | A diary of who changed what and when. |
34Frequently Asked Questions
Quick answers to the questions that come up most often.
35Summary and Key Takeaways
Remember these seven ideas
- There are four defaults, not one. The creation default, the Environment default, the control value and the default in code each live in a different place and act at a different moment.
- The Environment default reaches most people. Overrides help chosen groups, but everyone else receives the baseline, so it deserves the strongest protection in Production.
- Create flags disabled. Creation should never be the same event as release, and the Project safety setting helps stop creation defaults spreading to every Environment.
- Choose by the worse failure, not by habit. Off is right for risky new behaviour and wrong for protections, so ask what harm each direction could cause.
- Always write the default in code. Never leave it to the SDK, validate values from the dashboard and keep a register of defaults with reasons.
- Test and watch the fallback. Run the app with no connection, and count defaults used so silent fallbacks become visible.
- A default is a fallback, not a lock. Enforce real permissions on your servers, and keep legal or contractual rules out of flag defaults.