Client-Side SDK in Flagsmith

Client-Side SDK in Flagsmith

Client-Side SDK in Flagsmith

How a small piece of code inside your web page or mobile app asks a remote service which features to show, which values to use, and which users get what, all without shipping a new release.

Imagine you have just built a shiny new checkout page. Your team has tested it for weeks. On launch day, you push it to every customer at the same moment, and within ten minutes the support inbox is on fire because one payment provider behaves strangely with the new layout. Now you have two bad options: roll back the entire release, or scramble to fix the bug while customers keep failing to pay.

There is a much calmer way to live. You ship the new checkout page switched off, then turn it on for two percent of customers, watch the numbers, and only then widen the circle. If something smells wrong, you flip one switch and the old page is back in seconds. No new build, no app store review, no midnight deployment.

That switch lives in a tool called a feature flag service, and Flagsmith is one of the most popular open-source examples. The part of Flagsmith that sits inside your browser or phone app and talks to that switchboard is called the client-side SDK. This article explains exactly what it is, how it works from the inside, how it stays fast and safe, where it can hurt you, and how teams at real companies use the same idea every day.

!
How to read this guide

Each chapter explains one idea with a plain-English definition, an everyday comparison, and a real-world example. You can read it start to finish, or jump to the chapter you need.

1What Flagsmith Is and Why Feature Flags Exist

Before we talk about the client-side SDK, we need to understand the problem it helps solve and the service it connects to.

The old way: deploy equals release

For many years, software teams treated two very different events as one. Deploying means copying new code onto servers or into an app. Releasing means letting real users see and use the new behaviour. In the old world, the moment code was deployed, everyone saw it. That made every deployment a nerve-wracking event.

Think of a restaurant that can only change its menu by printing brand-new menus for every table at the same time. If a new dish turns out to be a disaster, the staff must run around collecting all the menus again. Now imagine the menu was a tablet on each table, and the manager could hide or show any dish from the kitchen office. That tablet is the idea behind a feature flag.

What a feature flag is

A feature flag (also called a feature toggle) is a named on/off decision that lives outside your code. Your code asks a simple question: “Is the new checkout enabled for this user?” The answer comes from a configuration you can change at any time, from a dashboard, without touching the code again.

Flags separate deploying from releasing. Code can travel to production quietly, days before anyone sees it. Then the business, not the build pipeline, decides when to turn it on.

Everyday analogy

A feature flag is like a light switch on the wall. The wiring and the bulb (the code) were installed long ago. Flipping the switch (the flag) decides whether the room is lit. You never rewire the house just to turn the light on or off.

What Flagsmith adds

You could write flags by hand with a text file, but that gets messy fast. Who changed it? Which users should see it? How do you roll it out to ten percent of people? Flagsmith is a ready-made platform for all of that. It gives you a dashboard where product managers and engineers manage flags, plus libraries (SDKs) that your applications use to read them.

Beyond simple on/off switches, Flagsmith also supports remote config, which means a flag can carry a value such as a number, a piece of text, or a small block of data. For example, a flag called “support-phone-number” could carry the number itself. Change it in the dashboard and every app shows the new number.

Flagsmith is open source and can be used as a hosted cloud service or run on your own servers. That choice matters to companies in regulated industries, because it lets them keep all flag data inside their own network.

Capability

Boolean flags

A simple yes or no. Is this feature on for this user right now?

Capability

Remote config

A flag that carries a value, such as a text label, a number, or a limit, which you can change without a release.

Capability

Segments

Groups of users defined by rules, such as “customers on the premium plan in Germany”.

Capability

Multivariate flags

One flag with several possible values, split across users by percentage, which is the backbone of A/B tests.

Real-world example: Facebook’s Gatekeeper

Facebook became well known in engineering circles for a system it called Gatekeeper, which lets engineers release code to employees first, then to a tiny percentage of people, and then to everyone. The company could therefore push code constantly while controlling who actually saw each change. Flagsmith applies the same idea in a product anyone can adopt.

2What “Client-Side” Really Means

The word “client” confuses many newcomers, so let us pin it down before going deeper.

Client and server in one minute

In almost every modern application there are two worlds. The server is a computer in a data centre that you control. The client is the device in the user’s hands: a web browser, a phone app, a tablet. The client asks, the server answers.

Flagsmith offers two families of SDKs, matching these two worlds. A server-side SDK runs inside your own backend code, in languages such as Python, Java, Go, or Node. A client-side SDK runs on the user’s device, in JavaScript for the browser, React, React Native, Flutter, Android, or iOS, among others.

Everyday analogy

Picture a hotel. The server-side code is the staff in the back office who have the master key and the full guest records. The client-side code is the guest standing in the lobby. The staff can see everything. The guest should only be told what concerns them: their room number, their breakfast time. A client-side SDK is built around that “tell the guest only what concerns them” idea.

Why the difference is important

The two worlds have very different trust levels. Your server is private. The user’s device is not: anyone can open browser tools and read what your web page contains, or inspect network traffic from a phone. Because of this, a client-side SDK is designed so that it never needs to be handed secrets or your full rulebook.

Instead of downloading the entire set of rules and calculating the answer itself, a client-side SDK asks the Flagsmith service, “Here is who I am. What flags apply to me?” The service does the thinking and replies with a short list of finished answers. This approach is called remote evaluation.

TopicClient-side SDKServer-side SDK
Where it runsBrowser, mobile app, deviceYour backend service
Trust levelLow, the user can inspect itHigh, you control the machine
Key it usesClient-side environment key, safe to be publicServer-side key, must stay secret
Who decides the answerThe Flagsmith service, returned as a finished listThe service by default, or the SDK itself in local evaluation mode
Typical userOne person per deviceThousands of different users in one process
i
Good to know

Server-side SDKs can optionally run in a local evaluation mode where they download the environment’s rules and decide on their own. Client-side SDKs do not do this. That is a deliberate safety choice, and we will return to it in the security chapter.

Real-world example: a streaming app on many devices

Companies such as Netflix run the same service on televisions, phones, game consoles, and browsers. The behaviour of each device family can differ, and an experiment can be shown on one family and not another. A flag system must therefore answer per device and per person, which is the exact job of a client-side SDK sitting inside each app.

3Core Concepts You Must Know

Flagsmith has a small vocabulary. Learn these words once and the rest of the system becomes easy to follow.

Organisation, project, and environment

An organisation is your company’s account. Inside it you create projects, usually one per product, such as “Mobile App” or “Customer Website”. Inside each project you create environments, which are separate copies of your flag settings, typically named Development, Staging, and Production.

Environments exist so that you can experiment freely. A flag can be on in Development, half-on in Staging, and off in Production, all at the same time. Each environment has its own identity for the SDK, which brings us to keys.

Everyday analogy

A project is like a theatre production. The environments are the rehearsal room, the dress rehearsal, and the opening night. The script (the list of features) is the same, but what the audience sees depends on which stage you are standing on.

Features, flags, and values

In Flagsmith, a feature is the named thing you want to control. For each environment, a feature has an enabled state (on or off) and optionally a value. The pair is what the SDK reads. People often say “flag” and “feature” interchangeably, and that is fine in daily talk.

Environment keys

Every environment has an environment key, a long random string that tells Flagsmith which environment the SDK is talking about. There are two kinds. The client-side environment key is meant to be placed in apps and is not a secret. The server-side key is private and must never appear in a browser or app bundle.

!
Warning

Never place a server-side key inside a mobile app or web page. Anyone can pull it out. Use only the client-side key on devices.

Identities and traits

An identity is a label for one user, such as a user ID or an email hash. When the SDK says “I am identity 42”, Flagsmith can give that person personalised answers. A trait is a small fact about that identity: their plan, their country, their app version, the date they signed up.

If no identity is given, the SDK is anonymous. It still receives the environment’s default flags, but it cannot receive answers tailored to one person.

Segments

A segment is a saved group defined by rules over traits. “Plan equals premium and country equals India” is a segment. Segments are how you say, “Turn this feature on for this group only”. The rules are evaluated on Flagsmith’s side, never exposed in full to the client.

Overrides and multivariate options

A segment can override the default value of a feature. An individual identity can also be overridden, which is useful when you want one named tester to see something special. A multivariate feature goes further by offering several named values and a percentage split, so that thirty percent of people receive option A, thirty percent option B, and forty percent the control.

1
Key per environment identifies where flags are read from
2
Kinds of key, public client key and private server key
3
Levels of answer: default, segment override, identity override

How the answer is chosen

When an identity asks for a flag, Flagsmith walks a short ladder. If a personal override exists for that identity, it wins. Otherwise, if the identity belongs to a segment with an override, that segment’s value wins. Otherwise the environment default applies. The first match on the ladder is the answer.

1

Identity override

A rule written for this exact person. Highest priority.

2

Segment override

A rule for a group the person belongs to.

3

Environment default

The fallback value set for everyone in that environment.

Real-world example: staff-first rollouts at Etsy

Etsy has publicly described deploying to production many times a day and using configuration flags to keep unfinished work hidden from shoppers. A very common first step in that style of working is a rule that shows the feature to employees only, which is the same as an identity or segment override sitting above the default.

4Architecture and Components

Now let us zoom out and see every piece involved when a client-side SDK reads a flag.

The big picture

The system has two halves. The control side is where people create and change flags: the dashboard and the core API behind it. The delivery side is where apps read flags at high speed: the edge API that SDKs call. Between them sits a data store that holds environments, features, segments, and identities, and a small real-time service that can nudge apps when something changes.

flowchart LR
  USER["User Device"] --> APP["Your App UI"]
  APP --> SDK["Flagsmith Client SDK"]
  SDK  CACHE["Local Cache on Device"]
  SDK -->|"HTTPS with client environment key"| LB["Load Balancer and CDN Edge"]
  LB --> EDGE["Flagsmith Edge API"]
  EDGE --> STORE[("Environment and Identity Store")]
  DASH["Flagsmith Dashboard"] --> CORE["Flagsmith Core API"]
  CORE --> STORE
  CORE --> RT["Real-time Update Service"]
  RT -.->|"change signal"| SDK
  SDK -->|"Batched usage analytics"| EDGE
Figure 1: Control side (dashboard and core API) and delivery side (edge API) with the SDK in the middle of the user’s device

Meet each component

On the device

Client SDK

A small library inside your app. It holds the environment key, the current identity, the latest flags, and the rules for when to refresh.

On the device

Local cache

Browser storage or phone storage where the last known flags are saved, so the app can start fast and survive bad networks.

Delivery

Load balancer and CDN

The front door that spreads traffic across many servers and, where possible, answers from a location near the user.

Delivery

Edge API

A lean, read-optimised service that answers “what flags does this identity get?” thousands of times per second.

Control

Dashboard and core API

Where humans create flags, build segments, and flip switches. Writes happen here, far less often than reads.

Control

Real-time service

A one-way channel that tells connected apps “something changed, please refresh”, so changes appear quickly without constant asking.

Why reads and writes are split

A busy product might change its flags a few dozen times a day, but read them millions of times a day. Systems with that lopsided shape are best built with a separate, fast path for reads. This is a classic idea in system design, often described as separating the read path from the write path. Flagsmith’s hosted platform follows it by running a distributed edge layer for SDK traffic, so that a spike in app usage does not slow down the dashboard, and a busy dashboard never slows down your customers.

Everyday analogy

A library keeps a quiet back office where librarians catalogue new books (writes) and a front desk where hundreds of visitors borrow books (reads). If cataloguing and borrowing used one single desk, both would crawl. Two desks, one shared catalogue, keeps everyone happy.

Self-hosted versus hosted

If you use Flagsmith’s cloud, all the delivery components above are run for you. If you self-host, you run the API, a database, and optionally the real-time component yourself, and you point the SDK to your own address instead of the default. The SDK behaves the same either way; only the web address it contacts changes.

Real-world example: Amazon’s read-heavy catalogue

Amazon’s product pages are read vastly more often than the catalogue is edited, and the company has long described separating those paths with caching layers close to the customer. Flag delivery has exactly the same shape, and the same architectural answer applies.

5Internal Working: What Happens at Startup

The first few hundred milliseconds of your app’s life are the most delicate. This is where the SDK wakes up, gets its settings, and decides what to show.

Step one: initialisation

Every client-side SDK begins with an initialisation call. You give it the environment key and a few options, such as the address of the Flagsmith service, which identity to use, and what to do if the network is unavailable. Think of this as introducing yourself at the front desk: “Hello, I am the Production website, here is my badge.”

During initialisation the SDK does several small jobs, usually in this order. It stores the settings in memory. It checks the local cache for flags saved earlier. It decides whether it needs to contact the server at all. If it does, it sends a request and waits. Meanwhile it exposes a loading state so your app knows the answers are not final yet.

Step two: the first request

The SDK calls the Flagsmith edge service over a secure connection. The key travels in a request header, which is how the service knows which environment to answer for. There are two shapes of request, and the SDK picks one based on whether an identity is present.

SituationWhat the SDK asksWhat comes back
No identity (anonymous visitor)“Give me the flags for this environment.”Environment defaults for every feature
Identity with traits“Here is who I am and some facts about me. What flags apply?”Personalised answers after segments and overrides are applied

In the second case, the SDK also sends the traits it knows. Flagsmith saves them against the identity, so future visits can use them even if the app does not resend everything.

Step three: building the in-memory map

The response is a compact list. Each entry says: the feature name, whether it is enabled, and its value if it has one. The SDK stores the list as a lookup table in memory. From that moment on, reading a flag inside your app is an instant local lookup, not a network trip. This is the single most important performance idea in the whole design: ask the network once, answer from memory many times.

Everyday analogy

When you check into a hotel, the receptionist hands you a printed card listing your room, Wi-Fi password, and breakfast time. You do not phone the front desk every time you need the Wi-Fi password. You glance at the card. The flag map in memory is that card.

Step four: telling the app it is ready

Once the map is built, the SDK fires a callback or updates observable state so your user interface can redraw. Frameworks like React expose this as a provider that re-renders components when flags arrive. Mobile SDKs offer listeners. This is the moment a hidden button might appear or a banner might change colour.

The loading problem

Because the first network request takes time, the app must decide what to show during that gap. There are three honest choices. It can wait and show a spinner, which is simple but slow-feeling. It can use default flags that you provided in advance, which is fast but may be wrong for a moment. Or it can use the cached flags from the last visit, which is usually right and also fast. Most production apps combine the second and third choices.

!
Tip

Always provide sensible default flags. If the network fails on a customer’s train ride, your app should fall back to the safe, known behaviour, not crash or flicker.

Real-world example: Google Chrome’s staged feature rollouts

Chrome ships new behaviour to a small percentage of installed browsers first, controlled by settings delivered from Google’s servers after the browser starts. If a problem appears, the setting is withdrawn without waiting for a new browser version. The browser has built-in safe defaults for the moment before those settings arrive, which mirrors the default-flags idea above.

6Data Flow and Lifecycle of a Flag

A flag has a short life on the device and a long life in the dashboard. Let us follow one flag from the moment a product manager clicks a button to the moment a customer sees the result.

From dashboard click to user screen

Suppose a product manager enables a feature called “new-checkout” for the Production environment and adds a segment rule for premium customers. The change is saved to the data store through the core API. If you use the real-time service, a small signal is also sent to apps that are listening. Apps then fetch fresh answers and update the screen.

sequenceDiagram
  participant PM as Product Manager
  participant DASH as Dashboard and Core API
  participant STORE as Data Store
  participant EDGE as Edge API
  participant SDK as Client SDK
  participant UI as App Screen
  PM->>DASH: Enable new-checkout for premium segment
  DASH->>STORE: Save change
  DASH-->>SDK: Real-time change signal
  SDK->>EDGE: Request flags for identity with traits
  EDGE->>STORE: Read environment, segments, overrides
  STORE-->>EDGE: Rules and values
  EDGE-->>SDK: Final list of flags for this user
  SDK->>UI: Notify that flags changed
  UI->>UI: Show new checkout to premium user
Figure 2: The journey of a flag change from the dashboard to a single user’s screen

The stages in plain words

1

Created

Someone defines the feature in the dashboard and gives it a clear name and description. It starts off in every environment.

2

Shipped dark

The code that checks the flag is deployed to production while the flag is still off. Nobody sees any change.

3

Targeted

The flag is turned on for staff or a small segment. Engineers watch logs and metrics.

4

Ramped

The audience grows in steps, such as one percent, ten percent, fifty percent, then everyone.

5

Fully released

The feature is on for everyone and has been stable for a while.

6

Cleaned up

The flag check is removed from the code, the old path is deleted, and the flag is archived. This last step is the one teams forget most often.

Short-lived and long-lived flags

Not every flag follows that full path. Some flags are meant to live for years. A kill switch is a long-lived flag that lets you turn off an expensive or risky feature instantly during an incident. A permission flag controls access to premium features. A remote config value might hold a support phone number forever. By contrast, a release flag should be short-lived, living only until the rollout finishes.

i
Good to know

Naming each flag with its purpose in mind, such as “release”, “experiment”, “ops”, or “permission”, helps your team decide how long it should exist and who is allowed to change it.

Real-world example: Flickr and continuous deployment

Flickr became famous in the late 2000s for deploying code many times per day, which they described as possible partly because unfinished features stayed behind flags. Engineers could merge incomplete work into the main code safely, because the flag kept it hidden until it was ready.

7Identities, Traits, and Segments in the Client

Personalisation is where client-side flags become powerful, and also where mistakes creep in.

Choosing a good identity

The identity is the string you give to Flagsmith to represent a person. Good identities are stable, meaning the same person gets the same string on every visit, and non-sensitive, meaning they do not reveal private details. An internal user ID or a random account number works well. A raw email address is risky because it is personal data that will travel across the network and be stored.

Stability matters because of percentage rollouts. When Flagsmith decides whether someone falls into the “ten percent” group, it does so by turning the identity into a number in a repeatable way. The same identity always lands in the same bucket, so a person does not see the new feature on Monday, lose it on Tuesday, and see it again on Wednesday.

Everyday analogy

Percentage rollouts work like a seat number at a concert. Your ticket number decides your row, and it never changes between visits. The venue can say “rows one to ten get early entry” and you will always be either in or out, consistently.

What about anonymous visitors?

Many sites have visitors who have not logged in. If you give no identity, every anonymous visitor receives the environment defaults, so you cannot run a consistent percentage rollout for them. A common solution is to generate a random anonymous ID on the first visit, store it on the device, and use it as the identity. Then the rollout is stable even before login. When the person logs in, you switch to their real identity, understanding that their bucket may change at that moment.

Traits: facts that unlock targeting

Traits are what make segments work. If you never send the user’s plan, you cannot build a segment for premium users. Typical useful traits are plan or subscription tier, country or region, app version, device type, and sign-up date. Keep them small, clear, and non-sensitive.

Good traits

  • Subscription plan name
  • App version number
  • Country or region code
  • Whether the account is a staff account
  • Sign-up date or cohort name

Risky traits

  • Full email address or phone number
  • Government identifiers
  • Health, religion, or other sensitive details
  • Anything that changes every second
  • Large blobs of text

Where the rules are evaluated

A key point for beginners: the segment rules are checked by Flagsmith, not by the SDK. The SDK sends traits, and the service returns answers. This means your app never sees the segment definitions. A curious user cannot open the page and read “premium users in India get the beta”. They only see the flags that apply to them.

Changing identity during a session

Users log in, log out, and switch accounts. The SDK provides ways to switch identity and to reset to anonymous. Each switch triggers a new request, because the answers may differ. Plan your interface for this moment: a button might appear or disappear after login, so your screens should handle a refresh smoothly rather than flash or jump.

!
Warning

Do not treat traits sent from the client as proof of anything. A user can change what their device sends. Use traits for convenience and experience, never for deciding who is allowed to access sensitive data. Real permission checks belong on your server.

Real-world example: Spotify-style gradual rollouts

Music and video apps routinely show a new home screen layout to a slice of listeners first, keeping each listener’s experience consistent across sessions and devices. That consistency depends on a stable identity feeding a repeatable bucket calculation, exactly as described above.

8Caching, Defaults, and Working Offline

Networks fail, phones go through tunnels, and servers have bad days. A well-built client-side integration keeps working through all of it.

Three layers of safety

Think of three layers, each catching what the previous one missed. First, the in-memory map answers all flag reads during a session. Second, the persistent cache on the device remembers flags between sessions. Third, your default flags provide a last-resort answer when nothing else is available.

flowchart TD
  START["App needs a flag value"] --> MEM{"In-memory map ready?"}
  MEM -->|"Yes"| ANSWER["Return value instantly"]
  MEM -->|"No"| CACHE{"Cached flags on device?"}
  CACHE -->|"Yes"| USECACHE["Use cached flags and refresh in background"]
  CACHE -->|"No"| NET{"Network reachable?"}
  NET -->|"Yes"| FETCH["Fetch from Flagsmith edge"]
  NET -->|"No"| DEFAULTS["Use default flags from the app"]
  USECACHE --> ANSWER
  FETCH --> ANSWER
  DEFAULTS --> ANSWER
Figure 3: The fallback ladder that keeps an app working when the network or service is unavailable

The persistent cache

Most client-side SDKs can store the last flags in the browser’s local storage or in the phone’s storage. On the next start, the SDK loads these flags immediately, so the first screen already reflects the correct features, and then it fetches fresh values in the background. This gives you the best of both worlds: instant start and eventual accuracy.

You can usually control how long cached flags are trusted. A short lifetime favours freshness. A long lifetime favours speed and offline resilience. Some SDKs let you choose to use stale cached flags if the network request fails, which is often the right call for apps used on poor connections.

Default flags: your safety net

Default flags are values you ship inside the app itself. They are used when there is no cache and no network, for example a first launch on an aeroplane. Choose them carefully. A good rule is that a default should be the safest, most conservative behaviour. A brand-new, unfinished feature should default to off. A critical safety feature, such as fraud protection, should default to on.

Everyday analogy

Defaults are like the emergency lighting in a cinema. The main lights are controlled from the booth (Flagsmith). If power fails, the emergency lights come on by themselves, and they are designed to show exits safely. They are not pretty, but they are predictable.

Stale data: a trade-off, not a bug

Caching means that, for a short moment, a user might see a flag value that has just been changed on the dashboard. For most features this is harmless. For a few, such as turning off a feature during an outage, you want changes to arrive fast. That is the job of polling and real-time updates, which we explore in the next chapter.

ChoiceBenefitCost
Long cache lifetimeFast start, less network use, works offlineChanges reach users slowly
Short cache lifetimeFresher flagsMore requests, more battery and data
Always wait for networkAlways fresh at startupSlow first screen, fails offline
Use stale on errorWorks through outagesMay show a slightly old state

Real-world example: Netflix and graceful degradation

Netflix has openly discussed designing its apps so that when a supporting service is slow or unavailable, the experience degrades gracefully instead of failing outright, for example by showing a simpler row of recommendations. Cached and default flag values serve the same spirit: the app keeps working in a reduced but sensible state.

9Staying Fresh: Polling and Real-Time Updates

A flag that cannot change quickly is only half a flag. Here is how the client learns that something has changed.

Option one: fetch on events

The simplest approach is to fetch flags only at certain moments: when the app starts, when the user logs in, and when the app returns to the foreground after being in the background. Many apps do nothing more, and for ordinary release flags that is perfectly adequate. A user who opens the app tomorrow will see tomorrow’s flags.

Option two: polling

Polling means asking again and again on a timer: “Anything new? Anything new?” You pick an interval, such as every thirty or sixty seconds. It is easy and robust, but it has costs. Every poll is a request that uses battery, mobile data, and server capacity. Multiply a small interval by millions of users and the numbers become large. Polling also has an inherent delay: a change can wait up to a full interval before a device notices.

Everyday analogy

Polling is like walking to the front door every minute to check whether the post has arrived. You will eventually catch it, but you waste many trips, and sometimes the post sits there for almost a minute before you look.

Option three: real-time with server-sent events

Flagsmith supports a real-time mode for client-side SDKs. The app opens a long-lived, one-way connection to a Flagsmith real-time service. When a flag changes, the service pushes a small notice down that connection. The SDK reacts by refreshing its flags. This technique is often called server-sent events, and it is a push model rather than a pull model.

Everyday analogy

Real-time updates are like a doorbell. You sit comfortably and do other things. When the post arrives, the bell rings, and only then do you walk to the door. No wasted trips, and almost no delay.

MethodSpeed of changeNetwork costBest for
Fetch on events onlySlow, at next start or loginVery lowRelease flags and slow experiments
PollingUp to one intervalModerate to highSimple setups, tolerant of delay
Real-time pushNear instantLow, one open connectionKill switches, live events, operational controls

Which one should you pick?

Let the importance of the flag guide you. A cosmetic experiment can wait. A kill switch that protects your payment system during an outage must be fast. Many teams combine approaches: fetch on start and foreground, use real-time for the small set of operational flags, and avoid constant polling on mobile devices where battery life matters.

!
Warning

An open real-time connection per user means your infrastructure must hold a very large number of simultaneous connections. If you self-host, size the real-time component with this in mind, and consider enabling it only where speed truly matters.

Do not let the screen flicker

When a flag changes while someone is using the app, the interface may shift under their fingers. A button that suddenly vanishes mid-tap is a poor experience. Good teams decide per feature whether a change should apply instantly or wait until the next screen or session. Flags that alter layout are often safer to apply at the next natural pause.

Real-world example: emergency switches during live events

Large online retailers such as Amazon prepare for peak events by building switches that can disable heavy, non-essential features, like personalised carousels, to protect the checkout path under extreme load. Such switches only help if every device learns about them within seconds, which is the reason real-time delivery exists.

10One Idea, Many Platforms

The client-side SDK is not one single library. It is a family of libraries that all follow the same pattern, each shaped to fit its platform.

The family

Flagsmith provides client-side SDKs for the main places software runs on the user’s side: plain JavaScript for browsers, React and other web frameworks, React Native for cross-platform mobile, Flutter, native Android, and native iOS. Each one offers the same basic abilities, which are initialising with a key, identifying a user, reading a flag, reading a value, setting traits, and listening for changes. What differs is the style, which feels natural to each platform.

Web

Browser JavaScript

Keeps cached flags in browser storage. Works in any page, with or without a framework.

Web framework

React-style providers

Wraps your app so that components automatically redraw when flags arrive or change.

Mobile

React Native and Flutter

One shared codebase for both phone platforms, using device storage for the cache.

Mobile native

Android and iOS

Native libraries that respect the phone’s background rules, battery limits, and storage.

Browser concerns

In a browser, flags usually load after the page starts. This creates a risk called flash of default content, where a user briefly sees the old design and then watches it change. Teams reduce this by hiding the affected area until flags are ready, by using cached flags from the previous visit, or by loading flags earlier in the page’s life.

Another browser concern is content blockers. Some privacy extensions block requests to well-known analytics and flag domains. If your flags fail to load for these users, your defaults must be good enough to keep the site working. Self-hosting the API under your own domain is another way to reduce this problem.

Server-side rendering and hydration

Many modern websites render a first version of the page on the server for speed and search engines, then let the browser take over. This is awkward for flags, because the server must know which flags apply before the page is sent, and the browser must agree with it afterwards. If they disagree, the page can flicker or even break.

The usual solution is for the server to fetch the flags once, embed that state in the page, and let the client SDK start from the same state instead of asking again. This idea is called hydration. It avoids a second network request and keeps the server and browser consistent.

Mobile concerns

On phones, apps are paused, resumed, and killed by the operating system all the time. A good integration refreshes flags when the app returns to the foreground, avoids heavy polling to protect battery, and stores the last good flags on the device. Remember also that mobile users may run old versions of your app for months. Your flags must therefore be safe for old code, which means never changing the meaning of an existing flag in a way that would confuse a version released long ago.

!
Tip

Send the app version as a trait. Then you can build a segment such as “version 5.2 or higher” and release a feature only to builds that know how to handle it.

Real-world example: long-lived mobile versions at Uber and WhatsApp

Companies with huge mobile audiences, such as Uber, must support many app versions in the wild at once, since a large share of users do not update promptly. Server-controlled switches let them fix or disable a problem feature for old versions without waiting for those users to install an update.

11Performance and Scalability

A flag system sits on the critical path of almost every screen, so it must be fast, light, and able to survive huge spikes.

Two kinds of performance

There is device performance, which is about how quickly the user sees the right thing, and service performance, which is about how many users the backend can handle. The client-side SDK influences both.

Device performance

Reading a flag from the in-memory map takes almost no time, so you can check flags freely while drawing your screen. The expensive part is the first network trip, which is why caching, defaults, and early loading matter. Another cost is the payload size. Each environment may have hundreds of features, and sending all of them to every device wastes data. Keep your flag list tidy, remove old flags, and avoid putting large blobs of text into flag values.

~0 ms
Time to read a flag from memory after startup
1
Network request needed to prepare a whole screen of flags
Small
Payload when you keep old flags cleaned up

Service performance and scale

Imagine a popular app with ten million daily users. If each user opens the app four times a day and each start triggers one flags request, that is forty million requests a day, or around four hundred sixty per second on average. Real traffic is lumpy. During a marketing campaign, the peak may be fifty times the average. The delivery layer must handle those peaks without breaking a sweat.

Flagsmith handles this by making the delivery path simple and read-focused. A request carries a key and an identity, and the answer is mostly a lookup plus some rule checks. The hosted platform uses a distributed edge layer so that requests are served from infrastructure near the user, and it keeps this layer separate from the dashboard so that heavy usage never blocks editing. Self-hosted teams usually put several copies of the API behind a load balancer, add a fast cache in front of the database, and scale each part independently.

Everyday analogy

Think of a railway station. A few people write the timetable in a back office, but thousands read the departure board every minute. Adding more departure boards is cheap and easy. Making the back office bigger would not help at all. Scaling flags is mostly about adding more departure boards.

Protecting the service from the crowd

There are several well-known defences against a stampede. Caching at the edge lets repeated identical requests be answered without touching the database. Rate limiting stops a misbehaving client from flooding the service. Back-off and jitter mean that when requests fail, clients wait a little longer and a little randomly before trying again, so a million devices do not all retry at the same second. Without jitter, a short outage can turn into a long one, because everyone rushes back at once. This pattern is known as a thundering herd.

RiskWhat it looks likeDefence
Traffic spikeSudden surge after a campaign or push notificationEdge caching, horizontal scaling, rate limits
Thundering herdAll clients retry together after an outageExponential back-off with random jitter
Slow startupUser waits on a spinnerCached flags, defaults, early loading
Oversized payloadLarge responses on slow networksArchive old flags, keep values small

Real-world example: push-notification stampedes

When a large app such as Uber or a news app sends a push notification to millions of phones at once, a huge share of them open the app within seconds. Every one of those app starts reads flags and configuration. Teams in this position design the configuration path to absorb that burst, usually with heavy caching and gentle retry rules.

12Security

The client is not a safe place. Security for client-side flags starts from one honest sentence: everything on the device can be read by the person holding the device.

What is public and what is not

The client-side environment key is public by design. Anyone can find it in your page or app. What protects you is that this key only allows reading the flags meant for clients, and it cannot change or delete anything. The server-side key, in contrast, has broader rights and must stay in your backend.

flowchart LR
  subgraph PUBLIC["Public zone - user device"]
    BROWSER["Browser or Mobile App"]
    CKEY["Client Environment Key"]
  end
  subgraph PRIVATE["Private zone - your backend"]
    SERVER["Your Backend Service"]
    SKEY["Server-side Key"]
    AUTHZ["Real Permission Checks"]
  end
  FLAGSMITH["Flagsmith Service"]
  BROWSER --> CKEY
  CKEY -->|"Read only flags for this identity"| FLAGSMITH
  SERVER --> SKEY
  SKEY -->|"Full environment access"| FLAGSMITH
  BROWSER -->|"Requests with user login token"| SERVER
  SERVER --> AUTHZ
Figure 4: The public zone only ever holds the client key, while real authorisation stays in the private zone

The five main security rules

1

Keep server keys off devices

If a server key is ever bundled into an app or page, treat it as leaked, revoke it, and create a new one.

2

Never hide secrets in flag values

A flag value is delivered to the device. Passwords, API tokens, and private URLs must never be stored as remote config for client use.

3

Never use a client flag as the only lock

A flag can hide a button, but a determined user can still call your backend directly. Always check permission again on the server.

4

Send minimal traits

Only send the facts needed for targeting. Avoid personal or sensitive data, which then travels and is stored.

5

Protect the dashboard

The people who can flip switches hold great power. Use single sign-on, role-based access, and audit logs.

Why remote evaluation helps security

Because the rules are evaluated by Flagsmith and only finished answers are sent down, the device never learns your targeting logic, such as which segments exist or how rollouts are calculated. Competitors cannot easily read your roadmap from your website. It also means that flags with sensitive targeting, such as “show to this named VIP customer”, do not leak the customer list into every browser.

!
Warning

Even a hidden feature is not secret. If the code for a not-yet-released feature is already inside your web bundle or app, a curious person can read it. Flags control visibility, not secrecy. Keep truly confidential work out of shipped code.

Governance and accountability

A feature flag can change what thousands of users see in seconds, so changes should be traceable. Flagsmith records who changed what and when, and offers features for approvals on sensitive environments. In a serious production setup, you would require a second person to approve changes to Production flags, just as you would for a code change.

Privacy and data protection

Identities and traits are data about people. If you serve users in regions with strict privacy laws, such as the European Union, treat them as personal data where applicable. Prefer pseudonymous identities, tell users in your privacy notice what you collect, and consider self-hosting or choosing a data region if you need data to stay in a specific location.

Real-world example: the Knight Capital incident

In 2012 the trading firm Knight Capital lost roughly four hundred million dollars in under an hour after a deployment went wrong. Part of the story was an old, long-forgotten flag being reused for a new meaning while stale code still existed on one server. It is a harsh, widely taught reminder that flags need clear ownership, clean-up, and careful change control.

13Monitoring, Logging, and Metrics

If you cannot see what your flags are doing, you are driving at night with the headlights off.

Three questions monitoring must answer

First, is the flag system healthy? Are requests succeeding, how long do they take, and how many fall back to defaults? Second, who is seeing what? How many users received the new feature, and from which segments? Third, what happened after the flip? Did errors, speed, or sales change when the flag changed?

Flag usage analytics

Client-side SDKs can report which flags were evaluated and how often, in small batches, so the dashboard can show which features are actually in use. This is valuable for spotting dead flags, which are flags nobody reads any more and which can be safely removed. Without usage data, teams are afraid to delete anything.

Logging for troubleshooting

SDKs can usually print what they are doing: which request they made, what came back, and which flags changed. Turn this on during development and when investigating a bug report. Keep it off or low in production, since logs on devices can be noisy and may expose identity information in places that other software can read.

Connecting flags to the rest of your monitoring

The best flag practice is to tag your errors, traces, and business metrics with the flag state. If your error tracker shows “crash rate doubled” and also shows that every crash had “new-checkout equals on”, you have found your culprit within minutes. Many teams therefore attach active flags as context to their error reports and analytics events, and Flagsmith offers integrations with common analytics and monitoring tools for this purpose.

Health

Request success and latency

Track how often the SDK reaches the service and how long it takes, especially at startup.

Health

Fallback rate

If many sessions rely on defaults, something is wrong with the network path or the service.

Adoption

Exposure counts

How many users were shown the new feature, split by segment and platform.

Impact

Before-and-after metrics

Errors, speed, sign-ups, and revenue compared across flag states.

Alerts that matter

Set alerts on things you can act on: a sudden jump in failed flag requests, a sharp rise in fallback usage, or an error spike that starts exactly when a flag was changed. Also keep a visible log of flag changes, so that during an incident the first question, “what changed recently?”, is answered in seconds.

!
Tip

During a rollout, pair each flag change with a calm waiting period and a short checklist of dashboards to watch. Ramping from one percent to ten percent is only safe if someone is actually looking at the graphs.

Real-world example: Netflix canary analysis

Netflix has described automated canary analysis, where a new version is released to a small slice of traffic and its health metrics are compared against the old version before it is widened. Flags allow the same careful comparison at the feature level rather than the whole-deployment level.

14Design Patterns That Work

Teams that use feature flags well tend to reach for the same handful of patterns again and again.

Pattern

Dark launch

Ship the code switched off, then turn it on for staff, then for a small share, then for all. Deploy and release become separate events.

Pattern

Percentage rollout

Grow the audience gradually, watching metrics at each step, with the power to go back instantly.

Pattern

Kill switch

A long-lived flag that disables a costly or risky capability during an incident, such as recommendations or a third-party integration.

Pattern

Experiment flag

A multivariate flag that splits users between variants and sends the exposure to your analytics tool for comparison.

Pattern

Entitlement flag

A flag that unlocks features by plan or tier. Useful for display, but always enforced again on the server.

Pattern

Remote config

Tunable values, such as limits, messages, and timeouts, adjustable without a release.

Keep the flag check close to the boundary

A strong structural habit is to check each flag in one place, near the edge of the feature, and then hand the decision to the rest of the code as a plain choice between two behaviours. Scatter the check across twenty files and the day you want to remove it, you will curse yourself. Wrap the decision in a small, named piece of code so the flag appears once and is easy to delete.

The two-path rule

Every flag creates two versions of your product: one with the feature and one without. Both paths need testing. This is why the number of live flags should stay small. Ten independent flags can in theory create more than a thousand combinations, and no team tests all of them. Keep flags independent where possible and retire them quickly.

Everyday analogy

Each flag is like a fork in a road. One fork is fine. Ten forks in a row create a maze that nobody has walked completely. Cleaning up a flag is like closing off the unused branch so the road is simple again.

Strangler-style migrations

Flags are excellent for replacing old systems piece by piece. You build the new path beside the old one, route a small group of users to the new path, compare results, and grow the group until the old path carries no traffic. At that point the old code is deleted. This approach is often called the strangler pattern, and flags are its steering wheel.

Real-world example: GitHub’s gradual releases

GitHub has publicly described releasing changes to employees first, then to small groups of users, using flag tooling it built in-house, so that bugs were found by colleagues rather than by customers. The same sequence is easy to reproduce with Flagsmith segments.

15Anti-patterns and Common Mistakes

Most flag trouble comes from the same few habits. Learn to recognise them early.

ANTI-PATTERN 01Avoid
The problem

Flags are created and never removed. Over the years the code becomes a thicket of old branches, and nobody remembers what any flag does.

Why it hurts

Dead paths still need to be understood and sometimes get activated by accident. Testing grows harder, and new engineers are afraid to touch anything.

Better approach

Give each release flag an owner and an expiry date. Add a clean-up task to the same ticket that created the flag. Use usage analytics to find flags nobody reads.

ANTI-PATTERN 02Avoid
The problem

Trusting a client-side flag as a security lock, for example hiding an admin button and assuming the admin actions are therefore safe.

Why it hurts

Anyone can call the underlying server endpoints directly. The flag only changed what the screen displays.

Better approach

Enforce permissions on the server, always. Let the flag decide visibility and experience only.

ANTI-PATTERN 03Avoid
The problem

Reusing an old flag name for a new meaning, or changing what an existing flag controls.

Why it hurts

Old app versions and old code paths still read the old name and now behave in surprising ways. This is the Knight Capital lesson.

Better approach

Create a new flag with a new name. Retire the old one only after you are sure no running version reads it.

ANTI-PATTERN 04Avoid
The problem

Blocking the whole app until flags arrive, with no timeout and no default.

Why it hurts

A slow network or a service hiccup freezes your product entirely. The flag system has become a single point of failure.

Better approach

Always ship defaults, use cached flags, and set a short timeout so the app proceeds with safe values.

ANTI-PATTERN 05Avoid
The problem

Putting everything into remote config: large documents, secrets, or deep business logic encoded in values.

Why it hurts

Payloads grow, secrets leak, and your product’s behaviour becomes impossible to reason about or test.

Better approach

Keep values small and simple. Keep secrets and heavy logic on the server.

A short list of everyday slips

  • Unclear names. A flag called “test2” tells nobody anything. Use names that say what the feature does.
  • Wrong environment. Changing Production when you meant to change Staging. Colour-code environments and require approvals for Production.
  • Unstable identity. Using a value that changes between visits, which makes users flip in and out of experiments.
  • Forgetting the off state. Testing only with the flag on. The off path must keep working, since it is your rollback.
  • Ignoring old app versions. Changing a flag in a way that confuses builds already out in the world.

16Experiments and Multivariate Flags

Turning a feature on is one question. Learning whether the feature is actually better is a different and more interesting question.

From switch to experiment

A simple flag has two states. A multivariate flag has several named values, each with a share of the audience. Imagine a flag called “checkout-button-text” with three values: “Buy now”, “Place order”, and “Complete purchase”. Flagsmith can give each value to a different slice of users, for example thirty percent, thirty percent, and forty percent, with the forty percent acting as the control, which is the group that sees the current wording and acts as the yardstick.

The client-side SDK receives only the one value that applies to the current identity. The user sees one button text and never learns that other versions exist. Because the identity decides the bucket in a repeatable way, a person keeps the same variant every time they return, which is exactly what a clean experiment needs.

Everyday analogy

An experiment is like a bakery trying three recipes for the same cake. Each recipe goes to a different table, nobody is told which is which, and the baker later counts which tables asked for a second slice. The flag is the waiter who quietly decides which recipe arrives at which table.

Measuring the result

Flagsmith decides who sees what, but the measuring usually happens in your analytics tool. The client-side SDK can pass the chosen variant to common analytics platforms, so each event, such as “order completed”, can be tagged with the variant that was active. Later you compare the groups: did the variant with “Place order” lead to more completed purchases than the control?

Good experiments follow a few simple habits. Decide the success measure before you start, so you do not go hunting for a result that looks nice. Let the test run long enough to cover a full weekly cycle, because Tuesday shoppers behave differently from Saturday shoppers. Change one thing at a time. And accept that a few percent difference on a small audience can be pure luck, so wait for enough users before drawing conclusions.

Exposure matters

A common beginner mistake is counting people who were assigned to a variant but never actually saw the changed part of the product. If the button text only appears on the final checkout step, then only people who reached that step were really exposed. Record the exposure at the moment the user sees the difference, not at the moment the app starts. This keeps the comparison honest.

!
Warning

Do not run several experiments that touch the same screen at the same time without thinking about overlap. Their effects mix together, and you will not know which change caused which result.

Ending an experiment

When the experiment has a clear winner, give the winning value to everyone by setting it as the default, then remove the other variants and the experiment code. Treat the experiment flag as short-lived work, with the same clean-up discipline as any release flag.

Real-world example: Netflix artwork testing

Netflix has publicly described testing different cover images for the same title across different groups of members, measuring which image led more people to press play. This is precisely the shape of a multivariate experiment: one decision point, several candidate values, and a stable assignment per member.

17Remote Config in Depth

Flags decide “whether”. Remote config decides “how much”, “which text”, and “how long”.

What remote config is good for

Remote config means that a feature carries a value, and the app reads that value at run time. Many things that engineers once hard-coded into an app are better as remote values, because they may need to change quickly and for good reasons. A support phone number changes. A promotional banner message changes. The maximum number of photos a free user may upload changes when the business changes its pricing. A timeout for a slow partner service may need to be longer during a busy week.

Example

Limits and quotas

Maximum uploads, page sizes, or retry counts, tuned without a release.

Example

Messages and labels

Banners, maintenance notices, and button text that marketing teams can adjust.

Example

Tuning knobs

Timeouts, cache lifetimes, and polling intervals adjusted live during busy periods.

Example

Minimum version notices

A value that tells very old app builds to show an “please update” screen.

Value types and discipline

A remote value is usually a piece of text, a number, or a true-or-false choice. Some teams also store a small structured document inside the text. This works, but be careful: a structured value that is wrong, such as a missing bracket, can crash the code that reads it. Always write the reading code defensively. If the value is missing, empty, or malformed, fall back to a sensible built-in value and continue.

Everyday analogy

Remote config is like the dial on an oven. The oven is built once, but the temperature can be turned up or down for every recipe. A dial with sensible limits is helpful. A dial that can be turned to “melt the oven” is a problem, which is why the code reading each value should also guard against silly numbers.

Keep values small and boring

Every value you add travels to every device, every time flags are fetched. A handful of short values costs almost nothing. Dozens of long documents will slow startup, especially on weak networks. Treat remote config as a place for small, clear settings, not as a general-purpose database.

Combine flags and values wisely

A single feature can have both an enabled state and a value. For example, a “free-upload-limit” feature could be enabled or disabled, and when enabled it carries the number of allowed uploads. Your code first checks whether the feature is enabled, and if so, uses the value. If it is disabled, the code uses its built-in standard limit. This two-step habit gives you both a safe off switch and a tunable dial.

!
Tip

Name remote values with their unit, such as “upload-limit-count” or “request-timeout-seconds”. A name that carries its unit prevents expensive confusion between seconds and milliseconds.

Real-world example: tuning during traffic peaks

Large consumer apps such as Uber adjust operational settings, like how often an app asks the server for updates, when the system is under strain. Doing this through remote values means the change reaches millions of devices in minutes, with no release at all.

18Testing an App That Uses Flags

Flags make products flexible, and flexibility makes testing more interesting. Here is how to keep quality high.

The two-path promise

Every flag you add means your app can behave in at least two ways. Your tests must prove that both ways work. Teams that test only the “on” path discover during an emergency that the “off” path, the one they planned to use as a rollback, has quietly broken. A rollback that does not work is worse than no rollback, because everyone trusts it.

Test layers

1

Small unit tests

Test the code for each behaviour on its own, with the flag decision passed in as a plain input. These tests are fast and do not need the network.

2

Component tests with fake flags

Replace the real SDK with a stand-in that returns chosen values, so you can see how a screen looks with the flag on, off, or carrying odd values.

3

End-to-end tests in a dedicated environment

Use a separate Flagsmith environment for automated tests, so test traffic never mixes with real data and test flag changes never touch customers.

4

Manual exploration in staging

Product and quality teams switch flags in Staging and explore combinations by hand, using identity overrides for named testers.

5

Careful production checks

After release, confirm real behaviour through dashboards and a small staff-only rollout before widening the audience.

Controlling what the test sees

Tests need to be predictable. If a test depends on a live flag that someone may change at any time, the test will fail randomly, and people will stop trusting the test suite. Use fixed values in automated tests. Reserve the live service for a small number of integration checks that are designed to confirm the connection works.

Testing the failure modes

The most valuable and most often skipped tests simulate trouble: the flag service is slow, returns an error, or is completely unreachable. Does the app start? Does it use the cache or the defaults? Does it hang? These tests prove your safety layers work before a real outage tests them for you.

A rollback you have never tested is only a hope.

Testing combinations sensibly

You cannot test every combination of ten flags. Instead, test each flag on its own against the normal baseline, and then test any pairs of flags that touch the same screen or share data. Keep a small list of “risky pairs” that the team agrees to cover.

Real-world example: Google’s emphasis on testing in production safely

Google’s engineering culture has long stressed that you cannot fully reproduce production in a lab, so changes should reach real users in small, observable steps with fast reversal. Flags support this by turning “testing in production” from a risky gamble into a controlled, reversible exercise.

19Deployment and Cloud Choices

Where Flagsmith runs affects cost, control, speed, and the legal comfort of your lawyers.

Three ways to run it

OptionWho runs the serversBest forWatch out for
Hosted cloud serviceThe Flagsmith teamTeams that want to start fast with no servers to look afterData lives with the provider, so check regions and policies
Self-hosted in your cloudYour teamCompanies needing control over data location and networkYou own scaling, upgrades, backups, and uptime
Private or on-premiseYour team inside your own networkHighly regulated industries, such as banks and healthcareMost work for your team, and mobile apps still need a reachable address

What a self-hosted setup involves

If you host Flagsmith yourself, you typically run the API as several identical copies behind a load balancer, so that if one fails, others keep serving. You connect them to a managed relational database and keep regular backups of it. You place a cache in front of the busiest read paths. You add monitoring on request rates, errors, and latency. If you use real-time updates, you also run the real-time component and make sure your load balancer allows long-lived connections.

Cloud platforms such as Amazon Web Services make this easy to assemble from managed parts: containers for the API, a managed database, a load balancer in front, and a content delivery network to place cached answers near users. You can spread copies across several availability zones, which are separate buildings within a region, so a single failure cannot take the system down.

Everyday analogy

Choosing a hosting option is like choosing between a hotel, a rented flat, and a house you built yourself. The hotel is ready the moment you arrive. The flat gives you more freedom. The house is entirely yours, including the leaking roof when it rains.

Reaching the service from devices

Whatever you choose, devices must be able to reach the API over the public internet with a valid secure certificate. Put the service on a clear address under your own domain if you can. This looks professional, avoids some content blockers, and lets you move the service later without releasing a new app version, because the address in the app never has to change.

High availability thinking

A flag service should degrade gently. Your client-side layers of cache and defaults already protect the user. On the service side, aim for no single point of failure: several API copies, a database with a standby ready to take over, and a plan for restoring from backup. Practise the plan. A backup you have never restored is another kind of hope.

Release management for the service itself

If you self-host, you will upgrade Flagsmith over time. Treat upgrades like any other important change. Try them in Staging first, read the release notes for changes to settings, and keep the ability to roll back. Interestingly, you can use feature flags to manage the rollout of your own applications while Flagsmith itself is updated carefully by conventional means.

Real-world example: regulated industries and data location

Banks and healthcare providers, such as large European banks, often require that user-related data stays inside defined regions or inside their own network. Self-hosting an open-source flag service is a common way to satisfy those rules while still getting the benefits of modern release control.

20Troubleshooting Guide

When a flag does not behave, the cause is almost always one of a small number of ordinary things. Work through them in order.

Symptom: the flag always shows its default

This usually means the SDK never received a successful answer. Check these in turn. Is the environment key correct and for the right environment? Is the address of the service correct, especially if you self-host? Is a content blocker, firewall, or missing network permission stopping the request? Did initialisation finish before your code read the flag? A frequent beginner error is reading a flag a split second before the SDK has finished loading it, which returns the default.

Symptom: the flag is on in the dashboard but off for my user

Here, the user is probably not matching your rule. Confirm that the identity is the one you think it is. Confirm that the traits were sent and spelled exactly as the segment expects, since “Premium” and “premium” may not match. Check the order of priority: a personal override on that identity wins over a segment, and a segment wins over the default. Finally, check the environment, since the change may have been made in Staging instead of Production.

Symptom: the flag changed but my app still shows the old value

This is caching and refresh timing. Ask how the app learns about changes: does it only fetch at start, does it poll, or does it use real-time? Look at the cache lifetime. Check whether the app is using stale cached flags because the network request failed. A quick test is to close the app fully and reopen it, or to clear the stored cache on a test device.

Symptom: users see different results from run to run

The identity is unstable. Perhaps it is generated freshly each time, or anonymous users get a new random ID after clearing their storage. Use a durable identity, and remember that private browsing windows and cleared data produce a brand-new anonymous visitor.

Symptom: the page flickers when it loads

The page is drawing before flags arrive and then redrawing. Show a neutral placeholder until the flags are ready, use cached flags, or hydrate the browser from flags fetched on the server.

Check first

Key and environment

Wrong key or wrong environment explains a surprising share of “it does not work” reports.

Check second

Identity and traits

Spelling, capitals, and identity stability decide whether rules match.

Check third

Timing and cache

Reading too early, or trusting an old cache, creates ghost problems.

Check fourth

Network path

Blockers, firewalls, and certificates can quietly stop the request.

Useful habits when investigating

  • Turn on SDK logging on a test device and read exactly what was requested and received.
  • Look at the identity in the dashboard. Flagsmith lets you inspect the traits it has stored and the flags it would return for that identity, which quickly separates “rule problem” from “SDK problem”.
  • Reproduce with a fresh identity to rule out leftover cached state.
  • Check the audit log to see who changed what recently. A teammate’s change an hour ago is a common culprit.
!
Tip

Write a short internal runbook with this checklist and the key dashboards. When an incident happens at two in the morning, a clear list beats clever memory every time.

Real-world example: incident reviews at Google and Etsy

Companies such as Google and Etsy are known for blameless postmortems, where a team studies what happened without hunting for someone to blame. Many such reviews begin with the question, “What changed recently?”, and a visible audit trail of flag changes answers it immediately.

21Best Practices Checklist

If you remember nothing else from this guide, remember the habits in this chapter. They separate calm, boring flag usage from exciting incidents.

Setting up

  • Use one environment per stage. Development, Staging, and Production each get their own key, so a test change can never touch real customers.
  • Use only the client-side key on devices. Store it in configuration rather than scattering it through the code.
  • Ship sensible defaults. Choose the safest behaviour for each flag when nothing else is known.
  • Turn on the persistent cache. Your app starts faster and survives bad networks.

Naming and ownership

  • Name flags for what they do, not for who asked or when. A clear name is documentation that never goes out of date.
  • Record an owner and a purpose. Use the description field and tags to mark each flag as release, experiment, ops, or permission.
  • Set an expected end date for every short-lived flag, and review old flags regularly.

Rolling out

  • Go in small steps. Staff first, then one percent, then ten, then fifty, then everyone.
  • Watch real metrics between steps, not just the calendar.
  • Agree on the rollback trigger in advance. For example, “if the error rate rises by a fifth, we switch it off.”
  • Test both paths. The off path is your safety net, so it must be as healthy as the on path.

Running day to day

  • Limit who can change Production. Use roles and approvals.
  • Keep an audit trail and display recent flag changes in your incident tools.
  • Prefer real-time updates only for operational flags. Let ordinary flags refresh when the app starts or returns to the foreground.
  • Send app version and platform as traits so you can target safely.

Cleaning up

  • Remove the code, then archive the flag. In that order, so no running version loses its switch unexpectedly.
  • Use usage analytics to prove a flag is no longer read before deleting it.
  • Make clean-up part of the definition of done for the original feature work.
!
Tip

Hold a short monthly flag review. Open the dashboard, sort by age, and ask of each old flag: “Can we delete this today?” Fifteen minutes a month prevents years of clutter.

22Advantages, Disadvantages, and Trade-offs

No design is perfect. A client-side SDK with remote evaluation gives you many strengths and a few costs, and you should choose with open eyes.

Advantages

  • Change behaviour without a new release or app store review
  • Instant rollback by flipping a switch
  • Targeting rules stay private on the service side
  • Safe to hold the public key on any device
  • Reading flags during a session is immediate
  • Same model across web and mobile platforms
  • Open source, with a self-hosting option

Disadvantages

  • Needs a network trip for fresh answers
  • Brief periods when a device holds slightly old values
  • Extra requests, data, and battery on mobile if misused
  • Adds a dependency that must be monitored
  • Flags multiply code paths and test effort
  • Identities and traits raise privacy duties

Key trade-offs in detail

Trade-offOne sideOther sideHow to decide
Remote versus local evaluationRemote keeps rules private and the device simpleLocal is faster and works offline but exposes the whole rulebookUse remote for clients, since devices cannot be trusted with rules
Freshness versus costReal-time and polling give quick changeFetch-on-event is cheap and calmFast for kill switches, slow for ordinary releases
Wait versus show defaultsWaiting gives correct stateDefaults give instant screensCombine cache with safe defaults
Rich targeting versus privacyMore traits allow finer targetingFewer traits protect usersSend only what you truly need
Many flags versus simplicityFlags give controlFlags create combinations to testKeep the live set small and retire fast
Remote evaluation trades a little freshness and a network trip for a lot of safety and control.

Consistency considerations

Because every device caches flags and refreshes at its own pace, two users can briefly see different versions of the same feature. This is called eventual consistency, and for most product features it is perfectly acceptable. It becomes a problem only when two parts of your system must agree at exactly the same instant. For example, if your front end shows a new pricing page but your server still calculates old prices, customers see confusing totals. For such cases, make the server the source of truth and have the client display what the server says.

You can think of this in terms of the CAP idea from distributed systems: when the network is unreliable, you must choose between always giving an answer and always giving the freshest answer. Flag clients nearly always choose to keep answering, using cached or default values, because an app that keeps working with a slightly old flag is better than an app that freezes.

Real-world example: eventual consistency at Amazon

Amazon’s engineers have long taught that some data, like a shopping cart, should favour staying available even if different replicas briefly disagree. Flag values follow the same philosophy, which is to stay available first and converge on the newest value shortly afterwards.

23Putting It All Together: A Full Rollout Story

Let us walk through a complete, realistic example, so every idea from the earlier chapters appears in one place.

The scenario

A fictional online grocery company, FreshCart, has a website and phone apps used by several million people. The team has rebuilt checkout and wants to release it safely. They use Flagsmith with client-side SDKs on the web and mobile apps, and a server-side SDK in their backend.

The plan

flowchart TD
  A["Create flag new-checkout in Flagsmith"] --> B["Deploy code with flag OFF everywhere"]
  B --> C["Enable for staff segment only"]
  C --> D{"Metrics healthy?"}
  D -->|"No"| R["Switch flag OFF and fix"]
  D -->|"Yes"| E["Roll out to 5 percent of users"]
  E --> F{"Errors and sales healthy?"}
  F -->|"No"| R
  F -->|"Yes"| G["Grow to 25, 50, then 100 percent"]
  G --> H["Keep stable for two weeks"]
  H --> I["Remove old code and archive flag"]
  R --> C
Figure 5: A safe rollout loop where every step has a clear way back

Step by step

1

Prepare

The team creates the flag with a clear description and owner. They set its default to off in every environment, and they ship the same default inside the apps in case nothing else is available.

2

Decide the identity and traits

Logged-in users are identified by an internal account number. Anonymous web visitors get a random ID stored on the device. Traits include plan, region, platform, and app version.

3

Dark launch

The new checkout code is deployed to production with the flag off. Nothing changes for customers, and the team verifies that the old checkout is untouched.

4

Staff first

A segment for staff accounts turns the new checkout on. Employees place real test orders for several days, and engineers fix issues found.

5

Five percent

A percentage rule releases the feature to five percent of customers on the newest app version only, because older versions lack a needed screen. Dashboards compare error rate, checkout completion, and speed against the other ninety-five percent.

6

A problem appears

The payment provider reports failures for one card type. The team flips the flag off. Because the website uses real-time updates for this operational flag, most sessions revert within seconds. The mobile apps revert at their next refresh.

7

Fix and resume

After the fix, they return to the staff segment, then five percent again, then grow in stages.

8

Backend agreement

The server checks the same flag with its own SDK for any price or tax rules, so the front end and backend never disagree about which checkout is active for a given order.

9

Clean up

After two stable weeks at one hundred percent, the old checkout code is deleted, the flag is archived, and the monthly review confirms it is gone.

What made this work

Every layer did its job. Defaults and caches protected the first screen. Stable identities kept users in a consistent bucket. Remote evaluation kept the rollout rules private. Real-time delivery gave the team a fast emergency stop. Server-side checks kept money logic honest. And a clean-up step stopped the flag from becoming permanent clutter.

Real-world example: Slack and gradual feature rollouts

Collaboration tools like Slack introduce major interface changes to a limited audience first, learn from their feedback, and widen the audience over time. The pattern is visible every time a new interface appears for some workspaces before others, and it relies on the same idea of server-controlled, per-user feature switches.

24Plain-English Glossary

A quick reference for every important word used in this guide, so you can look up any term in seconds.

Flag systems come with a lot of vocabulary, and teams often use the words loosely. Agreeing on exact meanings avoids confusion in meetings, in incident calls, and in code reviews. The table below gathers the terms in one place, each explained in a single clear sentence or two.

TermWhat it means
Feature flagA named switch outside your code that decides whether a feature is shown. It lets you separate deploying code from releasing it to users.
Remote configA value, such as a number or short text, that your app reads from Flagsmith at run time and that you can change without a new release.
EnvironmentA separate copy of all your flag settings, usually Development, Staging, and Production. Changing one environment never touches the others.
Client-side environment keyA public identifier placed in apps and web pages that lets the SDK read flags for one environment. It cannot change settings.
Server-side keyA private credential that belongs only in your backend. Leaking it gives others broad access to the environment.
IdentityA stable label for one user, such as an internal account number, used so the same person always gets consistent answers.
TraitA small fact about an identity, such as plan, country, or app version, used by segments to decide who matches a rule.
SegmentA saved group of users defined by rules over traits, used to target a feature at the right people.
OverrideA rule that replaces the default value for a segment or for one named identity. Personal overrides outrank segment overrides.
Multivariate flagA flag with several possible values, each given to a percentage of users. It is the basis of A/B tests.
Remote evaluationThe method where the service decides which flags apply and sends back only the finished answers, keeping the rulebook private.
Local evaluationA server-side mode where the SDK downloads the rules and decides for itself. It is not used by client-side SDKs.
Default flagsValues shipped inside the app that are used when there is no cache and no network. They should be safe and conservative.
Persistent cacheA copy of the last flags saved in browser or phone storage so the next start is instant and works offline.
PollingAsking the service for fresh flags again and again on a timer. Simple, but wasteful when the interval is short.
Server-sent eventsA one-way live connection from the service to the app, used to push a notice when flags change. The basis of real-time updates.
HydrationStarting the browser SDK from flag state already fetched on the server, so the page does not flicker or ask twice.
Kill switchA long-lived flag used to turn off a costly or risky capability instantly during an incident.
Dark launchDeploying code with its flag off so that it is in production but invisible until you choose to enable it.
Percentage rolloutGradually enabling a feature for a growing share of users, such as one, ten, fifty, and then one hundred percent.
Control groupThe set of users who keep the current experience in an experiment, serving as the yardstick for comparison.
Eventual consistencyThe idea that devices may briefly hold different values but all converge on the latest one shortly afterwards.
Thundering herdA flood of retries arriving at the same moment after an outage, often making the outage longer.
JitterA small random delay added to retry timing so that many devices do not all try again at the same second.
Dead flagA flag that no code reads any more. It should be removed to keep the product simple.
Audit logA record of who changed which flag and when, essential for investigating incidents and for accountability.
i
Good to know

Teams sometimes say “flag”, “toggle”, “switch”, and “feature” as if they were the same. In casual speech that is fine. In documentation and dashboards, pick one word and use it consistently so that newcomers are never confused.

Real-world example: shared language at large engineering teams

Companies such as Google and Amazon invest heavily in written design documents and shared vocabulary, because large teams can only move quickly when everyone means the same thing by the same word. A flag glossary, kept next to your runbook, serves the same purpose on a smaller scale.

25Frequently Asked Questions

Short answers to the questions people ask most often when they first meet the client-side SDK.

Q1Is it safe to put the client-side environment key in my website?
Yes, that is its purpose. It only allows reading the flags meant for clients and cannot change settings. The key that must stay hidden is the server-side key.
Q2Why does the client SDK not evaluate rules by itself?
Because the device cannot be trusted with your full rulebook. Letting Flagsmith evaluate the rules means the device only receives its own finished answers, and your targeting logic stays private.
Q3What happens if the network is down when my app starts?
The SDK uses cached flags from the previous session if it has them, otherwise the default flags you supplied. This is why defaults should always be safe and conservative.
Q4How quickly do changes reach users?
It depends on how you refresh. With real-time updates, within seconds. With polling, within one interval. With fetch-on-event only, at the next app start, login, or return to the foreground.
Q5Do I have to identify users?
No. Without an identity, everyone receives the environment defaults. You need an identity to personalise answers, to use segments, or to run stable percentage rollouts and experiments.
Q6Can the same person see different flags on phone and laptop?
Not if you use the same identity on both. A stable identity produces the same bucket everywhere. Different results usually mean one device is anonymous or is using a different identity string.
Q7Should I use real-time updates for every flag?
Usually not. Real-time connections cost infrastructure and can change the screen while someone is using it. Save them for operational flags such as kill switches, and let other flags refresh at natural moments.
Q8Can I use a flag to protect sensitive data or admin actions?
Not by itself. A flag changes what the interface shows, but a determined person can still call your backend. Always enforce permissions on the server.
Q9What is the difference between a feature flag and remote config?
A flag is an on or off decision. Remote config is a value, such as a number or a short piece of text. In Flagsmith, one feature can carry both an enabled state and a value.
Q10How many flags is too many?
There is no magic number, but if nobody can explain what a flag does, you have too many. Keep the number of live release flags low and archive them soon after launch.
Q11Does this work for single-page web apps and server-rendered sites?
Yes. Single-page apps initialise the SDK in the browser. Server-rendered sites often fetch flags on the server, embed the state in the page, and let the browser SDK start from that same state to avoid flicker.
Q12Can I run Flagsmith inside my own network?
Yes. It is open source and can be self-hosted. You then point the SDK at your own address, and everything else works the same way.
Q13What should I do before deleting an old flag?
Check usage analytics to confirm nothing reads it, remove the flag checks from the code, release that code, and only then archive or delete the flag. Remember that older mobile versions may still be out in the world.
Q14Is it a problem if two users briefly see different values?
For most product features, no. It is a normal result of caching and gradual refresh. Where exact agreement matters, let the server decide and have the client display the server’s answer.

26Summary and Key Takeaways

A client-side SDK is a small, careful messenger between your user’s device and a remote switchboard.

You started with a simple problem: releasing software is risky when deploying and releasing are the same event. Feature flags solve that by moving the decision about who sees what out of the code. Flagsmith packages that idea into a dashboard, an edge API, and a family of SDKs. The client-side SDK is the piece living in browsers and apps, and its design choices all follow from one honest fact: the device cannot be trusted with secrets.

Key Takeaways

  • Remote evaluation is the heart of the client SDK. The device sends an identity and traits, Flagsmith applies segments and overrides, and only finished answers come back. Your rulebook stays private.
  • Ask the network once, answer from memory many times. Flag reads inside a session are instant lookups, backed by a persistent cache and safe default flags for bad networks.
  • Use the right key in the right place. The client-side key is public and read-only. The server-side key never leaves your backend.
  • Choose freshness on purpose. Fetch on events for ordinary flags, and use real-time updates for kill switches and other operational controls.
  • Never treat a client flag as a security lock. It controls what people see, not what they may do. Enforce permissions on your server.
  • Roll out in small, measured steps with a rollback ready. Staff first, then a small percentage, with metrics watched at every stage and the off path kept healthy.
  • Clean up relentlessly. Give each flag an owner and an end date, remove the code, then archive the flag, so your product does not become a maze of forgotten switches.