Remote Evaluation Mode in Flagsmith
How Flagsmith decides, on its own servers, which features and values each user should receive, why this is the default way flags are read, and what it means for speed, safety, and cost.
Picture a busy airport. Thousands of passengers want to know one thing: “Which gate is my flight at?” There are two ways to answer. In the first way, every passenger is handed a thick binder containing every flight, every rule, and every last-minute change, and each person must work out their own gate. In the second way, passengers simply ask a desk, give their flight number, and the desk replies with one clear answer: “Gate 14.”
Feature flag systems face the same choice. Your application can either receive the whole rulebook and work out the answers itself, or it can ask the flag service and receive only the finished answer. Flagsmith calls the second approach remote evaluation, and it is the default way Flagsmith works. Every browser and phone app that uses a Flagsmith client-side SDK relies on it, and server-side SDKs use it unless you deliberately switch them to the alternative.
This article explains remote evaluation from the ground up: what “evaluation” even means, how a single request travels through the system, how Flagsmith decides the answer, what can go wrong, how to keep it fast and safe, and when you might choose the other mode instead.
Every chapter gives a plain-English definition, an everyday comparison, and a real-world example. Read it straight through, or jump to the chapter you need using the headings.
1Feature Flags and Why Evaluation Matters
Before we can talk about where the decision is made, we need to be clear about what the decision is.
A quick refresher on feature flags
A feature flag is a named switch that lives outside your code. Your code asks, “Is the new search page enabled for this person?” and a configuration, which you can change at any time from a dashboard, supplies the answer. This lets a team ship code quietly, turn it on for a few people, widen the audience slowly, and turn it off instantly if something goes wrong.
Flagsmith is an open-source platform that manages these switches. Besides plain on/off flags, it supports remote config values, which are numbers or pieces of text that a flag can carry. It also supports segments, which are groups of users defined by rules, and multivariate flags, which hand out several different values to different percentages of people.
What does “evaluation” mean?
A flag in the dashboard is only a recipe. It might say: “This feature is off for everybody, except it is on for users in the premium segment, except it is also on for one named tester, and ten percent of users should get the blue button while ninety percent get the green button.” That recipe is not an answer. Someone, or something, must look at one specific user and work out the single final answer for that user. This act of turning a recipe plus a user into a final answer is called evaluation.
A restaurant menu is like the flag recipe. It lists every dish and its rules, such as “vegetarian only on Mondays” or “kids’ portion for under twelve”. Evaluation is the waiter looking at you, checking the rules, and telling you what you can actually order tonight. The menu does not choose for you. The waiter does.
The big question: who evaluates?
Evaluation has to happen somewhere. In Flagsmith there are exactly two places it can happen. It can happen on Flagsmith’s servers, which is remote evaluation. Or it can happen inside your own server application, which is local evaluation. Everything in the rest of this guide flows from that single choice.
Remote evaluation
Your app sends a small request, Flagsmith evaluates, and a finished list of answers comes back. This is the default.
Local evaluation
Your server downloads the rules once, refreshes them regularly, and evaluates every user itself without a network call per request.
Real-world example: Facebook’s Gatekeeper
Facebook’s well-known Gatekeeper system decides, for a given person and a given feature, whether the feature is visible. The decision is made by central infrastructure rather than being hard-coded into each page. Flagsmith’s remote evaluation follows the same shape: a central service holds the rules and returns a decision per user.
2What Remote Evaluation Mode Is
The idea is simple. The complexity lives in the details, which we will unpack one layer at a time.
The definition
Remote evaluation means that every time your application needs flags, it makes a request to the Flagsmith API, and the API computes the right values and returns them. The SDK in your application is little more than a messenger: it carries your question out and your answer back. The rules, the segments, and the percentage calculations never leave Flagsmith’s side.
In remote mode, an SDK usually asks one of two questions. The first is, “What are the flags for this environment in general?” That question has no user attached, so the answer is the environment defaults. The second is, “What are the flags for this particular identity, who has these traits?” That second question is where segments, personal overrides, and percentage splits come into play.
Why it is the default
Remote evaluation is the default because it is the simplest and safest place to start. There is nothing to configure beyond a key. The answers are always computed using the latest rules, because the rules are read at the moment of the request. The application never needs to understand how segments work. And the same method works on every platform, from a tiny script to a mobile app on a phone with a weak signal.
Remote evaluation is like phoning a travel agent. You say your name and travel dates, and the agent checks the latest prices and rules and tells you your fare. You do not need to carry a book of airline tariffs. The price you hear is always up to date, but you do have to make the call.
What travels in each direction
| Direction | What is sent | Why |
|---|---|---|
| App to Flagsmith | An environment key, and optionally an identity and its traits | So Flagsmith knows which environment and which user to evaluate for |
| Flagsmith to app | A compact list: feature name, enabled state, and value | The finished answers, ready to use |
Notice what is not sent back: the segment definitions, the percentage rules, the list of other users, or other environments. The caller receives only what it needs to behave correctly for one user.
Where remote evaluation is used
All client-side SDKs, meaning those that run in browsers and phones, use remote evaluation only. Server-side SDKs, which run in your backend in languages such as Python, Java, Go, Ruby, and Node, use remote evaluation by default and can optionally be switched to local evaluation. So when people say, “Flagsmith evaluates remotely”, they usually mean, “it is working in its normal, out-of-the-box way”.
The exact names of settings and options differ between SDKs and change as versions advance. The ideas in this guide stay the same, but always check the documentation for your language when you configure something specific.
Real-world example: a weather app asking a server
Think of any weather application. It does not hold a forecast model inside the phone. It asks a server for the forecast for your location and shows the reply. Remote evaluation applies the same habit to feature decisions: a powerful central brain, and a light, simple asker on the device.
3Remote Versus Local Evaluation
You cannot fully understand one mode without seeing the other beside it.
How local evaluation works, briefly
In local evaluation, a server-side SDK uses a secret server-side key to download a complete snapshot of the environment, including every feature, segment, rule, and override. This snapshot is often called the environment document. The SDK keeps it in memory and refreshes it on a timer, for example once a minute. When your code asks for flags for a user, the SDK works out the answer on the spot, using the snapshot, with no network call at all.
Local evaluation is like owning your own copy of the airline fare book. Looking up a price is instant and works without a phone line, but your copy is only as fresh as the last time you bought a new edition, and you now hold the whole book, including parts you rarely need.
Side-by-side comparison
| Topic | Remote evaluation | Local evaluation |
|---|---|---|
| Where the decision is made | On Flagsmith’s servers | Inside your server process |
| Network call per evaluation | Yes, unless you cache | No, only a periodic refresh |
| Speed of one evaluation | Network round trip, typically tens of milliseconds or more | In-memory, a tiny fraction of a millisecond |
| Freshness of rules | Always the latest at request time | As fresh as the last refresh |
| Key needed | Client key or server key | Server-side key only |
| Works in a browser or phone | Yes | No, because the rulebook would be exposed |
| Traits stored by Flagsmith | Yes, when sent with an identity | Generally not stored, so persistent traits are not kept this way |
| Dependence on Flagsmith at runtime | Every request depends on the API unless cached | Only the refresh depends on the API |
| Request volume sent to Flagsmith | Grows with your traffic | Small and steady |
Local evaluation hands your whole rulebook to the process that runs it. That is acceptable inside your own protected backend, and unacceptable inside a browser or phone, which is exactly why client-side SDKs never use it.
Same answer, different route
An important design goal is that both modes should give the same answer for the same user and the same rules. Flagsmith calculates percentage splits in a repeatable way from the user’s identity and the feature, so a person who falls in the “ten percent” group remains in it no matter which mode computed the answer. Still, because the two modes read data at different moments, they can briefly disagree right after a change, which we explore in the freshness chapter.
Real-world example: DNS lookups
Every device on the internet faces a similar choice when it needs an address for a website name. It can ask a DNS server each time, which is always correct but costs a trip, or keep a local cache, which is fast but may be briefly out of date. Flag evaluation modes are the same trade-off wearing different clothes.
4Core Concepts Behind Every Evaluation
Eight small ideas appear in every remote evaluation. Learn them once and the rest is easy.
Environments and keys
An environment is a separate copy of your flag settings, such as Development, Staging, and Production. Each has its own environment key. When your app sends a request, the key tells Flagsmith which environment’s rules to use. A client-side key is meant to be public and can only read flags. A server-side key is secret and has broader rights.
Features and their states
A feature is the named item you control. In each environment it has an enabled state, either on or off, and optionally a value. The pair of state and value is what a remote evaluation returns for every feature.
Identity and traits
An identity is a stable label for one user, such as an internal account number. A trait is a small fact about that identity, such as their plan, country, or app version. In remote mode, you can send traits along with the request, and Flagsmith can store them against the identity for later.
Segments
A segment is a saved group defined by rules over traits, for example “plan equals premium and country equals Germany”. Segments let you target a feature at a group instead of at everyone.
Overrides
An override replaces the default for a segment or a single identity. A personal override outranks a segment override, and a segment override outranks the environment default.
Multivariate options
A multivariate feature has several possible values and a percentage split among them. Remote evaluation picks the one value that belongs to the user, in a repeatable way.
Think of a theme park. The environment key is the park you are visiting. The identity is your wristband. Your traits are details such as your height and whether you bought the fast pass. The segments are rules like “fast-pass holders skip the queue”. The evaluation is the gate attendant checking your wristband and telling you which line to stand in.
The priority ladder
When several rules could apply, Flagsmith follows a fixed order. A personal identity override wins first. If there is none, a matching segment override applies. If there is none of those either, the environment default is used. This ordering is the reason a named tester can always see a feature that is off for everyone else.
Identity override
A rule written for this exact person. Highest priority.
Segment override
A rule for a group the person belongs to.
Environment default
The fallback for everyone else in that environment.
Real-world example: staff-first releases at Etsy
Etsy has publicly described deploying many times a day and keeping unfinished work hidden behind configuration. A typical first step is showing a feature to employees only, which is the same as a segment or identity override sitting above a default of off.
5Architecture and Components
Let us zoom out and see every piece involved when remote evaluation answers a request.
The picture
The system has a control side, where humans create and edit flags, and a delivery side, where applications read flags at high speed. Between them sits a store of data that holds environments, features, segments, and identities. Remote evaluation lives on the delivery side.
flowchart LR
APP["Your Application with Flagsmith SDK"] -->|"HTTPS request with environment key"| LB["Load Balancer and CDN"]
LB --> API1["Flagsmith API Node 1"]
LB --> API2["Flagsmith API Node 2"]
API1 --> ENGINE["Evaluation Engine"]
API2 --> ENGINE
ENGINE --> CACHE["Fast Cache"]
ENGINE --> STORE[("Environment, Segment and Identity Store")]
DASH["Dashboard"] --> CORE["Core API"]
CORE --> STORE
ENGINE -->|"Finished list of flags"| APP
APP -->|"Optional usage analytics"| LB
Meet the components
SDK in your application
Holds the key, sends requests, receives answers, and can hold a short-lived copy of the answers in memory.
Load balancer and CDN
Spreads requests across many API servers and, where possible, answers repeated requests from a nearby location.
API nodes
Identical copies of the service. If one fails, others keep answering.
Evaluation engine
The logic that applies segments, overrides, and percentage splits to produce one final answer per feature.
Store and cache
The permanent record of rules and identities, with a fast cache in front for repeated reads.
Dashboard and core API
Where people make changes. Writes are rare compared with reads.
Separating reads from writes
A product might change its flags a few dozen times a day but read them millions of times. Systems with this shape work best when the read path is separated from the write path, so that heavy reading never slows down editing. Flagsmith’s hosted service uses a distributed delivery layer for SDK traffic, so busy applications do not compete with the people working in the dashboard.
A town library has one quiet desk where librarians add new books and many fast desks where visitors borrow them. If both jobs shared one desk, both would crawl. Two desks sharing one catalogue keeps everyone moving.
Real-world example: Amazon’s read-heavy catalogue
Product pages at Amazon are read far more often than they are edited, and the company has long described using caching layers close to customers to serve those reads. Flag evaluation has the same lopsided shape and the same architectural answer.
6Internal Working: One Request, Step by Step
Let us follow a single request from the moment your code asks for a flag until the answer is in your hands.
Step one: your code asks
Somewhere in your application, a piece of code needs a decision. It asks the SDK for the flags of a user. The SDK checks whether it already has a fresh enough copy of the answer in its own memory. If it does, it returns that immediately and the story ends. If not, it prepares a network request.
Step two: building the request
The SDK attaches the environment key to the request so that Flagsmith knows which environment to use. If you gave an identity, it includes the identity and any traits you supplied. The request travels over a secure connection, which protects it from being read or changed in transit.
Step three: the front door
The request reaches the load balancer, which selects a healthy API node. The node first checks the key. An unknown or revoked key is rejected at once. A valid key identifies one environment, and the node loads that environment’s rules, usually from its fast cache, and only occasionally from the main store.
Step four: finding the identity
If an identity was provided, the node looks it up. If it has been seen before, its stored traits and any personal overrides are loaded. Traits sent in the current request are merged in, and, depending on how you sent them, saved for later. If the identity is brand new, it is created or treated as new, depending on the endpoint and settings.
Step five: the evaluation engine decides
For each feature in the environment, the engine runs the priority ladder from Chapter 4. It checks for an identity override first. Then it checks every segment the identity belongs to, by applying each segment’s rules to the identity’s traits. Then it falls back to the environment default. For multivariate features, it turns the identity and the feature into a number in a repeatable way, and uses that number to pick a value according to the percentage split.
Step six: the reply
The engine assembles a compact list with one entry per feature, each containing the name, the enabled state, and the value. The node sends it back. The SDK stores it in memory, optionally for a short time so repeated calls do not trigger repeated requests, and hands the answers to your code.
Code asks for flags
The SDK checks its own short-term memory first.
Request is built
Key, identity, and traits are attached and sent securely.
Key is verified
The node confirms the key and loads that environment’s rules.
Identity is resolved
Stored traits and overrides are combined with the traits just sent.
Engine decides
Overrides, segments, defaults, and percentage splits produce one answer per feature.
Answer returns
A compact list comes back and the SDK hands it to your code.
It is like ordering at a counter. You say what you want, the cashier checks your loyalty card and today’s offers, applies the right discounts in the right order, and hands back one final receipt. You never see the discount rulebook, only the total.
Real-world example: payment authorisation
When you tap a card in a shop, the terminal sends a small request to a payment network, which applies many hidden rules and returns a single approve-or-decline answer. The shop never sees the rules. Remote evaluation has this same shape, a small question and a single decisive answer.
7The Two Kinds of Question
A remote evaluation request comes in two flavours, and choosing the right flavour affects both correctness and cost.
Flavour one: environment flags
The first flavour asks, “Give me the flags for this environment.” There is no identity, so no segment or personal rule can apply, and the reply is the environment defaults. This is the cheapest and simplest request. It is perfect for settings that are the same for everyone, such as a global maintenance banner or a site-wide kill switch.
Flavour two: identity flags
The second flavour asks, “Give me the flags for this identity, who has these traits.” The reply reflects segments, personal overrides, and percentage splits. This is what you need for gradual rollouts, targeting by plan or country, and experiments. It does more work, because Flagsmith must look up the identity and evaluate rules, and it may also store the traits you send.
| Question type | Personalised? | Typical use | Relative cost |
|---|---|---|---|
| Environment flags | No | Global switches, maintenance modes, site-wide settings | Lowest |
| Identity flags | Yes | Rollouts, targeting, experiments, per-user features | Higher |
Persistent traits and transient traits
When you send traits with an identity request, there are two possible intentions. In one, you want Flagsmith to remember the traits, so they are available in future requests and visible in the dashboard. In the other, you want to use the traits for this evaluation only and then forget them. This second kind is called a transient trait, and it is helpful for facts that change constantly or that you would rather not store, such as the current basket value or a one-time session detail. The details of how to mark traits as transient vary by SDK, so check your documentation.
Use the lightest question that gets the job done. If a flag is the same for everybody, ask the environment-level question. Save identity-level questions for flags that truly differ per user.
Why remembering traits is useful
Stored traits make identity evaluation smarter over time. A mobile app might send the country once at sign-up. Later, a web page can ask for flags for the same identity without resending it, and Flagsmith still knows the country. Support staff can also open an identity in the dashboard and see exactly which flags that person receives, which turns mysterious bug reports into quick investigations.
Stored traits are data about people. Do not send sensitive personal details. Use pseudonymous identities, and send only the facts you genuinely need for targeting.
Real-world example: Spotify-style consistent experiences
Music apps keep a listener’s experience consistent across phone, laptop, and speaker. That consistency depends on a stable identity and remembered attributes held centrally, not on each device guessing separately. Remote evaluation with stored traits gives you the same property.
8Data Flow and Lifecycle
A flag has a long life in the dashboard and thousands of short lives in requests. Let us follow both.
From dashboard click to user answer
Suppose a product manager turns on a feature called “new-search” for a segment of premium users. Here is what happens, in order, when that premium user next triggers a remote evaluation.
sequenceDiagram participant PM as Product Manager participant DASH as Dashboard and Core API participant STORE as Data Store participant API as Flagsmith API participant ENG as Evaluation Engine participant APP as Your Application PM->>DASH: Enable new-search for premium segment DASH->>STORE: Save change APP->>API: Request flags for identity with traits API->>STORE: Load environment rules and identity STORE-->>API: Rules, segments, overrides, stored traits API->>ENG: Evaluate every feature ENG-->>API: One answer per feature API-->>APP: Finished list of flags APP->>APP: Show new search to premium user
Life of a flag in the dashboard
Created
A feature is defined, named, and described. It starts off in every environment.
Shipped dark
Code that reads the flag is deployed while the flag is off.
Targeted
Staff or a small segment gets the feature, and the team watches the results.
Ramped
The audience grows in measured steps.
Released and stable
Everyone has the feature and metrics look healthy.
Cleaned up
The check is removed from the code and the flag is archived.
Life of one evaluation
One evaluation is short. It is born when your code asks, lives for a few milliseconds as a request travels and is processed, and dies when its answer is used or cached. The important insight is that remote evaluation reads the rules at the moment of the request. A change made one second ago in the dashboard is already part of the next request’s answer, unless something along the way, such as an SDK cache or a CDN, held on to an older copy.
It is like checking a live departures board versus a printed timetable. The board always shows the latest gate. The timetable is quicker to read in your pocket but may be out of date by the time you get to the airport.
Real-world example: Flickr and continuous deployment
Flickr was famous in the late 2000s for deploying many times a day, which its engineers explained was made safe partly by hiding unfinished features behind switches. A central, always-current decision point meant a feature could be turned on or off without another deployment.
9Inside the Evaluation Engine
The engine is the heart of remote evaluation. Understanding how it thinks makes every strange result easy to explain.
How a segment is matched
A segment is a bundle of rules. Each rule looks at one trait and applies a test, such as “equals”, “does not equal”, “contains”, “is greater than”, “is in a list”, or “matches a pattern”. Rules can be grouped. A group can require that all its rules match, or that any of them match. Groups can sit inside groups, which allows rules such as “plan is premium and (country is India or country is Germany)”.
When the engine evaluates an identity, it takes the identity’s traits and tests every segment. An identity may belong to zero, one, or many segments at the same time. If several segments override the same feature, the engine needs a tie-breaker, and Flagsmith uses a documented priority order for segment overrides. You can see and change that order in the dashboard. Treat the priority list as part of your design, not an afterthought.
A segment is like a membership club with entry rules. “Anyone over eighteen who lives in the city and holds a library card.” The engine is the doorkeeper who checks your documents against the rules. You may qualify for several clubs, and when two clubs offer different perks, the club ranked higher on the list wins.
What happens when a trait is missing
A rule can only test a trait that exists. If the identity has never been given a country, a rule about country cannot match. For “not equal” style rules, treatment of a missing trait can surprise people, so test such rules with an identity that lacks the trait. When something refuses to match, the first thing to check is whether the trait was sent at all, and whether it was spelled and capitalised the same way as in the rule.
How a percentage split stays stable
Percentage rollouts and multivariate splits must be fair and repeatable. If the engine used a random number each time, a user could see the new feature on one request and the old one on the next. Instead, the engine combines the identity and the feature into a single value and maps it onto a number line from zero to one hundred. The same inputs always produce the same number, so a given person stays on the same side of the line, request after request, server after server.
A rollout set to ten percent means that identities whose number falls below ten receive the feature. Raising it to twenty keeps everyone who already had it and adds more. Nobody who was in drops out when you widen the circle, which is exactly what a careful rollout needs.
Why the feature name matters in the split
If the number depended on the identity alone, the same lucky ten percent of users would always be first in every rollout of every feature, and they would become unwilling test subjects for everything. Mixing the feature into the calculation shuffles who is early for each feature, which spreads the risk of early exposure fairly across your user base.
When a user says, “I should have this feature but I do not”, open that identity in the dashboard. Flagsmith can show the traits it stored and the resulting flags, and that single view usually reveals the missing or misspelled trait.
Real-world example: Google Chrome field trials
Chrome assigns each installed browser to experimental groups using a stable, repeatable assignment, so a given browser stays in the same group while a feature is tested. The concept is the same stable bucketing that Flagsmith applies to identities.
10Latency and Performance
The honest cost of remote evaluation is time. Every evaluation that is not cached must cross a network.
Where the time goes
The delay for one remote evaluation is the sum of several small pieces. First comes the network trip from your server or device to Flagsmith and back, which depends on distance and quality of connection. Then comes the secure connection setup, which is slower the first time and quicker when a connection is reused. Then queueing and processing inside Flagsmith, which is usually small. Finally comes the transfer of the reply, which depends on how many features you have and how large their values are.
Sending a letter to ask a question takes time even if the answer is a single word. The reading and answering at the other end is quick. Most of the delay is the postal journey, which is why the sender who lives far away waits longer.
Why this matters for a busy server
Suppose a web page needs five flag decisions, and your server asks Flagsmith five times in a row, each trip taking forty milliseconds. That is two hundred milliseconds added to the page, with nothing else done. Now imagine that happening for every visitor. The cost is not only slower pages. Your server holds each request open while it waits, which uses up memory and worker capacity, so traffic spikes hurt more than they should.
Five ways to keep it quick
Ask once, not many times
Fetch all flags for a user in one request and read individual answers from that single result.
Keep connections alive
Reuse a long-lived connection so the secure handshake is paid once, not on every request.
Cache for a short time
Hold the answers in memory for seconds or minutes, where a small delay in freshness is acceptable.
Keep the payload lean
Archive old flags and keep values small so the reply stays tiny.
Use a nearby endpoint
Use the closest region or a self-hosted instance near your servers, to shorten the trip.
Set sensible timeouts
Never wait forever. A short timeout plus a safe default keeps your own service responsive.
Do not put remote calls inside tight loops
A classic mistake is evaluating a flag inside a loop that processes thousands of items, such as checking “is the new price rule enabled?” once for each product on a page. If each check is a network call, the page will take minutes. Evaluate once before the loop, store the answer in a plain variable, and use that variable inside the loop.
Never make an uncached remote evaluation call inside a loop, inside a database transaction, or while holding a lock. A slow network moment will freeze everything waiting behind it.
Real-world example: Amazon’s famous latency findings
Amazon engineers have long shared the finding that small increases in page delay measurably reduce sales. That is why large retailers obsess over every extra round trip in a request, and why a flag lookup should never be allowed to quietly add hundreds of milliseconds.
11Scalability
A flag service sits on the critical path of almost every request. It must handle crowds without breaking.
Understanding the load
Imagine an application with ten million daily users. If each user triggers three flag requests a day, that is thirty million requests per day, about three hundred and fifty per second on average. Real traffic is lumpy. A marketing campaign or a push notification can multiply the rate by fifty within a minute. A remote evaluation service must be built for the peak, not the average.
How the load is spread
flowchart TD
CLIENTS["Millions of Clients and Servers"] --> EDGE["CDN and Edge Layer"]
EDGE --> LB["Load Balancer"]
LB --> N1["API Node A"]
LB --> N2["API Node B"]
LB --> N3["API Node C"]
N1 --> RC["Shared Fast Cache"]
N2 --> RC
N3 --> RC
RC --> DB[("Primary Data Store")]
DB --> REP[("Read Replica or Standby")]
AUTO["Auto Scaling Rules"] -.->|"add or remove nodes"| LB
The scaling toolbox
Horizontal scaling means adding more identical API nodes rather than making one node bigger. Because evaluation is mostly a read operation with no memory of earlier requests inside the node, any node can answer any request, which makes this style of scaling simple. Caching keeps the most common data, such as an environment’s rules, in memory so the main database is rarely touched. Replication keeps extra copies of the data, so reads can spread and a failure does not lose everything. Auto scaling adds nodes when traffic rises and removes them when it falls.
A supermarket opens more checkout lanes when the queue grows and closes them when the shop empties. Every lane works the same way, so a customer can join any lane. Adding lanes is far cheaper than building a bigger single lane.
Hosted versus self-hosted scale
If you use Flagsmith’s hosted service, the provider runs a distributed delivery layer and is responsible for scaling it. If you host Flagsmith yourself, you own that job. You will run several API nodes behind a load balancer, give them a managed database with backups, add a cache, and monitor request rates and latency. Plan your capacity from the peak traffic you expect, with comfortable headroom.
Protecting the service
| Risk | What it looks like | Defence |
|---|---|---|
| Traffic spike | Sudden surge after a campaign | Edge caching, auto scaling, rate limits |
| Thundering herd | All clients retry at the same second after a failure | Exponential back-off with random jitter |
| Hot key | One environment receives vastly more traffic than others | Cache the hot environment’s rules in memory on every node |
| Runaway client | A bug calls the API in a tight loop | Rate limiting and alerts on unusual request rates |
Real-world example: Uber and push-notification surges
When a large app such as Uber sends a push notification to many phones at once, a big wave of app opens arrives within seconds, and each open reads configuration. Teams in that position design the configuration path to absorb the wave with heavy caching and gentle retry rules.
12Reliability and Failure Handling
Remote evaluation puts a network and another company’s service between your code and a decision. Plan for that service being slow or gone.
What can go wrong
Several things can fail on the way to an answer. The network can drop packets or become slow. The service can be overloaded, restarting, or temporarily down. A key can be wrong or revoked. A certificate can expire. A firewall in your own network can block outgoing traffic. Each of these produces the same visible result: your code did not receive an answer.
Decide the failure behaviour in advance
The question that matters is not “what if it fails?” but “what do we want to happen when it fails?” The answer is usually one of three choices, and you choose per flag. Fail closed means treating the feature as off, which is the safe default for new or risky features. Fail open means treating the feature as on, which suits essential behaviour such as fraud checks that must never be skipped. Use the last known value means carrying on with the most recent good answer, which suits features where a slightly old decision is better than a surprise change.
flowchart TD
ASK["Code needs a flag"] --> MEM{"Fresh answer in SDK memory?"}
MEM -->|"Yes"| USE["Use it"]
MEM -->|"No"| CALL["Call Flagsmith with a short timeout"]
CALL --> OK{"Answer received?"}
OK -->|"Yes"| SAVE["Store in memory and use it"]
OK -->|"No"| LAST{"Last known good answer exists?"}
LAST -->|"Yes"| STALE["Use last known answer and retry later"]
LAST -->|"No"| DEF["Use safe default for this flag"]
Timeouts, retries, and back-off
A timeout limits how long your code will wait. Without one, a stalled request can hold a worker forever. A retry tries again after a failure, which helps with brief glitches. But retries can make a bad situation worse when thousands of callers retry together. Exponential back-off makes each retry wait longer than the last, and jitter adds a small random amount so callers do not all strike at the same moment. Together they let a struggling service recover instead of being flattened again.
Circuit breakers
A circuit breaker stops calling a service that keeps failing. After several failures in a row, the breaker “opens”, and your code immediately uses the fallback without even trying the network. After a pause, it lets a single test call through. If that works, the breaker closes and normal service resumes. This protects both your application, which stops wasting time on doomed calls, and the failing service, which gets room to recover.
A circuit breaker in your house trips when too much current flows, protecting the wiring. A software circuit breaker trips when too many calls fail, protecting your application and the service from a spiral of wasted effort.
Offline and fallback options
Many server-side SDKs let you supply default values through a handler that is used when the API cannot be reached. Some also offer an offline mode where the SDK reads flags from a local file or from a snapshot you provide, never calling the network. These are valuable for tests, for isolated environments, and as an emergency parachute. Check your SDK’s documentation for the exact options.
Rehearse failure. Once in a quiet period, block the flag service from a test environment and watch what your application does. It is much better to find a hanging page in a rehearsal than during a real outage.
Real-world example: Netflix and Hystrix-style resilience
Netflix popularised circuit breakers and fallback responses for its own microservices, so that if a recommendation service failed, members still saw a simpler page instead of an error. The same philosophy applies to a flag lookup: failure should lead to a calm fallback, not a broken screen.
13Caching Strategies in Remote Mode
Caching is how remote evaluation becomes fast enough for busy systems. It is also where most freshness surprises come from.
Cache layers
Between a flag change and a user’s screen there can be several caches, and each has its own lifetime. The SDK memory cache holds a user’s answers for a short while. The CDN or edge cache may hold repeated identical responses for seconds. The server-side cache inside Flagsmith holds environment rules. And, on devices, a persistent cache may keep the last answers across restarts. Each layer trades a little freshness for a lot of speed.
| Layer | Where it lives | Typical lifetime | Effect |
|---|---|---|---|
| Request-level memory | Inside one web request in your server | Milliseconds to seconds | Avoids repeat calls while building one page |
| Application cache | In your server process or a shared cache you run | Seconds to minutes | Protects Flagsmith and your latency during traffic peaks |
| Edge or CDN cache | Near the user | Seconds | Absorbs repeated identical requests |
| Flagsmith internal cache | On the API nodes | Managed by Flagsmith | Keeps the main database calm |
Choosing a cache lifetime
Ask a single question: how long can a wrong answer survive without causing harm? For a cosmetic experiment, five minutes may be fine. For a kill switch that protects a payment system, thirty seconds may already be too long. You can give different flags different freshness needs by using separate caches or by treating a small set of critical flags specially.
Cache keys must include the identity
When you cache identity-level answers, the cache key must include the identity and, ideally, a fingerprint of the traits. If you cache by environment only, user A’s personalised answer may be handed to user B. This is a subtle and serious bug, because it shows people features they should not have. Always make the key as specific as the question.
A shared cache that ignores the identity can leak one person’s feature access to another. Test this explicitly with two different identities that should receive different answers.
Stale-while-revalidate
A popular technique is to serve the slightly old cached answer immediately while quietly fetching a fresh one in the background, ready for the next request. The user never waits, and the cache keeps itself current. The price is that one unlucky request may see an answer that is a few seconds out of date, which is usually acceptable.
A newsagent keeps today’s papers on the shelf and sends a boy to fetch the latest edition while serving you. You walk away with the paper in your hand straight away, and the next customer gets the fresher one.
Real-world example: content delivery at Cloudflare and Fastly style CDNs
Content delivery networks became essential because serving the same content from a nearby copy is dramatically faster than fetching it from the origin each time. Their well-known use of short-lived caches and background refresh is the very pattern that works for flag responses.
14Freshness and Consistency
Remote evaluation starts out fresh. Every layer you add to speed it up makes it a little less so. Here is how to think about that honestly.
The freshness spectrum
With no caching at all, a flag change in the dashboard shows up on the very next request. With a one-minute application cache, a change may take up to a minute to reach every server, and different servers may hold different ages of answer at the same moment. With a persistent device cache, a user’s phone may keep an older answer until the next refresh. None of these is wrong. They are design choices.
Eventual consistency in plain words
Because many caches refresh independently, two users, or two servers, can briefly see different answers to the same question. They will all converge on the newest answer shortly afterwards. This behaviour is called eventual consistency, and nearly all large-scale systems accept it in exchange for speed and availability.
In the language of distributed systems, when the network is unreliable you must choose between always answering and always giving the newest answer. Flag systems nearly always choose to keep answering, using cached or default values, because an application that works with a slightly old flag is far better than one that stops.
When consistency really matters
A few situations demand that two parts of your system agree at the same instant. If your front end shows a new price display but your backend still computes the old price, customers see confusing totals. For such cases, make one place the single source of truth. Evaluate the flag once on the server, and send the result to the front end as part of the response, so both sides use the same decision.
Cosmetic changes
Colours, wording, and layouts can tolerate minutes of difference with no harm.
Gradual rollouts
A few seconds of mixed answers during a ramp is expected and harmless.
Money and pricing
Evaluate once, on the server, and pass the result forward.
Kill switches
Keep caches short, or use a faster refresh path for these few flags.
Read your own writes
When a person changes a flag in the dashboard and immediately tests the result, they expect to see it. If an application cache holds the old answer, they may conclude that the change did not work and change it again, which creates confusion. Teams often shorten cache lifetimes in Staging, or provide a way to bypass the cache for testers, so changes can be verified at once.
Real-world example: Amazon’s shopping cart
Amazon’s engineers have written about favouring availability for the shopping cart, accepting that replicas may briefly disagree because the cart can always be merged and corrected later. Flag values follow the same philosophy: stay available first, and converge on the latest value shortly afterwards.
15Security
Remote evaluation has a quiet security advantage: the rules stay where they are, and only finished answers travel.
The rulebook never leaves
Because the engine runs on Flagsmith’s servers, the caller never receives the segment definitions, the list of other features’ targeting, or the percentage rules. This is the reason client-side SDKs can safely run in a browser. A curious user opening the developer tools sees only the flags that apply to them, not your product roadmap or your customer segments.
Keys and what they can do
Keep the two key types firmly apart. The client-side key can be shipped in apps because it only reads flags for the identity you give it. The server-side key is a secret. It belongs in your backend’s secret storage, never in source code, logs, mobile apps, or web pages. If a server-side key leaks, treat it as compromised: revoke it and issue a new one.
Use the minimum key
If a component only needs to read flags for users, give it the client key.
Store secrets safely
Keep server-side keys in a secrets manager and rotate them on a schedule.
Use secure connections only
All traffic must travel over encrypted connections with valid certificates.
Never trust client-sent traits for access
A user can alter what their device sends. Use traits for experience, and check real permissions on the server.
Guard the dashboard
Use single sign-on, roles, approvals, and audit logs for who may flip switches in Production.
Privacy of identities and traits
In remote mode, Flagsmith may store identities and traits you send. These are data about people. Use pseudonymous identities, such as an internal account number rather than an email, and send only what you need for targeting. If you serve users in regions with strict privacy laws, tell users what you collect, and consider self-hosting or a regional deployment if data must stay in a specific place. Transient traits let you use a fact for one evaluation without storing it.
Never hide secrets inside flag values. A value is delivered to whatever asked for it. Passwords, tokens, and private addresses must never be stored as remote config.
Remote versus local, from a security view
Local evaluation downloads a full snapshot of the environment, so the process holding it knows all your rules. That is fine in a well-protected backend, but it makes the secret key and the snapshot more sensitive. Remote evaluation reveals less, because every caller gets only its own answers. If you cannot protect a process fully, remote mode is the more conservative choice.
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. A forgotten flag whose old meaning was reused, together with stale code on one server, was part of the story. It is a harsh reminder that flags need clear ownership, change control, and clean-up.
16Monitoring, Logging, and Metrics
Because remote evaluation depends on a network call, you must be able to see how that call is behaving.
What to measure
Measure the success rate of flag requests, the latency at the median and at the slow tail, the fallback rate, meaning how often your code had to use a default or an old value, the cache hit rate, and the request volume over time. Averages hide trouble. Always look at the slowest one percent of requests, because that is where your unhappiest users live.
Success rate
The share of requests that return a valid answer. A drop is an early warning.
Tail latency
The time taken by the slowest requests, which shows hidden problems that averages bury.
Fallback rate
If many requests use defaults, your users may be getting the wrong experience.
Request volume
A sudden rise often means a bug, such as a loop calling the API repeatedly.
Logging with care
Log enough to investigate: the environment, the feature name, whether the answer came from the network, the cache, or a default, and how long it took. Avoid logging full traits or identities in ordinary logs, since logs are widely readable and long-lived. When you need detail to solve a bug, turn on verbose SDK logging temporarily in a test environment.
Tie flags to everything else you watch
The best practice is to attach the active flag values to your error reports, traces, and business events. When your error tracker shows that crashes doubled, and every crashing session has “new-search equals on”, you have found the cause within minutes. Flagsmith offers integrations with common analytics and monitoring tools so this context can flow automatically.
Alerts worth having
- Failed flag requests rising above a normal level for several minutes.
- Latency tail rising beyond the budget you set for flag lookups.
- Fallback rate rising, meaning users are not receiving real decisions.
- Request volume spiking far above the usual pattern.
- Error spike right after a flag change, which points straight at the change.
The audit trail
Flagsmith records who changed what and when. In an incident, the first question is always, “What changed recently?” A visible, searchable change log turns a long investigation into a one-minute check. Surface recent flag changes inside your incident tools if you can.
Real-world example: Google SRE and the golden signals
Google’s Site Reliability Engineering practice teaches teams to watch latency, traffic, errors, and saturation for every service. A remote flag dependency deserves the same four signals, tracked from your side as a client of the service.
17Request Volume and Cost
Every remote evaluation is a request, and requests are the unit by which many hosted services measure usage.
Why volume grows faster than you expect
If every page view or API call on your side triggers a flag request, the number of requests grows in step with your traffic. A product with a million daily page views and four flag lookups per view produces four million requests a day. If the usage is metered, that can become a real line in your bill. Even for a self-hosted setup, more requests means more servers.
Ways to reduce request volume
The cheapest request is the one you never make. Fetch all flags once per user per visit instead of once per flag. Cache answers for a short and sensible time. Use environment-level requests for flags that do not vary by user. Avoid calling the API from places that run constantly, such as every cell of a spreadsheet job or every iteration of a loop. And consider local evaluation for high-volume backend services, which we cover in the next chapter.
Think of a mobile data plan. Checking the weather once is cheap. Checking it every second burns through your allowance for no benefit. Smart habits, such as checking once and remembering the answer for a while, keep the bill small.
Know your plan and limits
Hosted plans and self-hosted deployments have different rules about request limits and fair use, and those rules change over time. Check the current terms for your plan, and set an alert on your own usage so a bug does not surprise you at the end of the month.
Add a simple counter in your own code for flag requests. A sudden jump after a release is the fastest way to catch an accidental loop before it hurts your bill or the service.
Real-world example: cloud bills and chatty services
Many companies have discovered large cloud bills caused by chatty services making needless calls to each other. Large engineering organisations regularly describe trimming unnecessary internal calls to cut cost and improve speed. A remote flag lookup is one more call that deserves the same scrutiny.
18When to Choose Local Evaluation Instead
Remote evaluation is the right default, not the right answer for every system. Here is how to tell when another mode fits better.
Signs that remote mode is straining
Watch for a few warning signs. Your flag lookups show up as a noticeable slice of request latency. Your flag request volume is large, steady, and growing. Your service has strict speed targets, measured in single-digit milliseconds. You run in an environment with unreliable or slow access to the flag service. Or you evaluate flags for many different users inside one backend process, such as a batch job or an API gateway. These all point toward evaluating inside your own process.
What you gain with local evaluation
Local evaluation answers in memory, so lookups become almost free. Request volume to Flagsmith drops to a small, steady refresh. Your service keeps working through a short outage of the flag service, because it already holds the rules. And you no longer pay a network trip inside your hottest code paths.
What you give up
The first cost is freshness: changes arrive on the next refresh, not instantly. The second is exposure: your process now holds the whole environment’s rules, so the server-side key and the process must be well protected. The third is memory and processing: your service stores the snapshot and runs the engine. The fourth is trait storage: in local mode, traits you pass are generally used only for that evaluation and are not saved back to Flagsmith, so features that depend on remembered traits need extra thought. And local evaluation is available only for server-side SDKs, never for browsers or phones.
flowchart TD
START["Where does your code run?"] --> Q1{"Browser or mobile app?"}
Q1 -->|"Yes"| REMOTE1["Remote evaluation is the only option"]
Q1 -->|"No, a trusted backend"| Q2{"Strict latency or very high request volume?"}
Q2 -->|"No"| REMOTE2["Stay with remote evaluation and add a short cache"]
Q2 -->|"Yes"| Q3{"Can you tolerate changes arriving after a short refresh delay?"}
Q3 -->|"No"| REMOTE3["Remote evaluation with careful caching for critical flags"]
Q3 -->|"Yes"| Q4{"Can you protect the server-side key and snapshot?"}
Q4 -->|"Yes"| LOCAL["Consider local evaluation"]
Q4 -->|"No"| REMOTE4["Stay with remote evaluation"]
A mixed approach is normal
You do not have to choose one mode for your whole company. A busy internal service might use local evaluation for speed, while your website and apps use remote evaluation because they must. A small, rarely used admin tool can stay remote forever with no cache at all. Match the mode to the job.
A taxi driver in a small town may ask the dispatcher for each fare, since the calls are few. A driver on a busy airport rank memorises the fare chart, because a call for every passenger would be hopeless. Both are right for their own situations.
Real-world example: DNS caching resolvers
Large networks run caching DNS resolvers close to their users because asking the global DNS for every lookup would be too slow and too costly. The resolver accepts that answers can be a little stale. Moving from remote to local flag evaluation applies the same trade for the same reasons.
19Design Patterns That Work
Teams that run remote evaluation well tend to reach for the same handful of patterns.
One lookup per request
At the start of handling a request, fetch all flags for the user once, then pass the result around like any other piece of request data.
Flag gateway
Wrap Flagsmith behind a small internal module. The rest of the code asks your module, so timeouts, caching, and defaults live in one place.
Safe defaults table
Keep a written list of the default for each flag and the reason, so failure behaviour is a decision rather than an accident.
Kill switch
A long-lived flag that disables a costly or risky capability during an incident, kept on the fastest refresh path.
Dark launch and ramp
Ship code switched off, enable for staff, then raise the percentage step by step while watching metrics.
Decide once, propagate
Evaluate on the server and send the decision to the front end, so both sides always agree.
The flag gateway in depth
The flag gateway is the single most useful pattern. Instead of calling the SDK directly from fifty places, create one small module with a clear job: given a user, return the flags, applying a timeout, a short cache, a circuit breaker, and the safe defaults. Every other part of your code uses that module. When you later change cache lifetimes, switch some services to local evaluation, or replace the SDK, you change one place.
A hotel has one concierge who knows how to book tables, taxis, and tickets. Guests do not each call restaurants themselves. When the booking system changes, only the concierge needs training.
Keep the decision near the boundary
Check each flag in one place, close to the edge of the feature, and hand the rest of the code a plain choice between two behaviours. A flag check scattered across twenty files is a flag nobody dares remove. A flag checked once, in a clearly named spot, can be deleted in an afternoon.
The two-path rule
Every flag gives your product two versions: with the feature and without. Both must be tested. Keep the number of live flags small, and retire them promptly. Ten independent flags create over a thousand combinations, and nobody tests all of them.
Strangler-style migration
Flags are excellent for replacing an old system step by step. Build the new path beside the old one, route a small group to it, compare results, and grow the group until the old path carries no traffic. Then delete the old code. The flag is the steering wheel of the whole migration.
Real-world example: GitHub’s gradual releases
GitHub has publicly described releasing changes to employees first and then to small groups of users using its own flag tooling, so that bugs were found by colleagues rather than customers. The same staff-first sequence is easy to reproduce with Flagsmith segments.
20Anti-patterns and Common Mistakes
Most remote evaluation trouble comes from a small set of repeat offences. Learn to spot them early.
The problem
Calling the flag service once per flag, or once per item inside a loop.
Why it hurts
Latency adds up, request volume balloons, and your workers sit idle waiting on the network.
Better approach
Fetch all flags for the user once, keep the result in a variable, and read from it.
The problem
No timeout and no default, so the application waits on the flag service as long as it takes.
Why it hurts
A slow or failing flag service now freezes your own service. A helper has become a single point of failure.
Better approach
Set a short timeout, add a circuit breaker, and always provide a safe default.
The problem
Caching flag answers without including the identity in the cache key.
Why it hurts
One user’s personalised answer is served to another, leaking features and corrupting experiments.
Better approach
Key the cache by environment, identity, and a fingerprint of the traits.
The problem
Using a flag as the only lock on a sensitive action, such as hiding an admin button and assuming the action is protected.
Why it hurts
Anyone can call the underlying endpoint directly. The flag only changed what the screen shows.
Better approach
Enforce permissions on the server every time. Use flags for experience and release control only.
The problem
Generating a new random identity on every request.
Why it hurts
Percentage rollouts become random per request, users flip between experiences, and Flagsmith fills with worthless identities.
Better approach
Use a stable identifier, or for anonymous visitors, a random ID stored once and reused.
The problem
Flags that are created and never removed.
Why it hurts
Dead code paths pile up, testing grows harder, and an old flag reused with a new meaning can cause serious incidents.
Better approach
Give each release flag an owner and an end date, and make clean-up part of the original task.
Everyday slips
- Wrong environment. Using the Production key in a test, or editing Production when you meant Staging.
- Trait spelling mismatch. Sending “Premium” when the segment expects “premium”.
- Forgetting the off path. Testing only with the flag on, then finding the rollback broken.
- Sending too many traits. Large or sensitive traits slow requests and raise privacy risk.
- Ignoring failure modes. Never testing what happens when the flag service is unreachable.
21Testing and Troubleshooting
Flags make products flexible, which makes testing and debugging more interesting. A clear method keeps both calm.
Testing layers
Unit tests with plain inputs
Pass the flag decision into your code as a simple value, and test both behaviours quickly with no network.
Tests with a fake flag provider
Replace the SDK with a stand-in that returns chosen values, including odd, missing, and slow ones.
Integration tests in a dedicated environment
Use a separate Flagsmith environment for automated tests so test traffic never mixes with real data.
Failure rehearsals
Block the service, slow it down, and revoke a key in a test setting, then watch how your application behaves.
Careful production checks
After release, confirm behaviour through dashboards and a staff-only ramp before widening the audience.
Troubleshooting: the flag always shows its default
This almost always means no successful answer arrived. Check the key and that it belongs to the right environment. Check the address of the service, especially for self-hosted setups. Check for firewalls, proxies, or missing network permission. Check that your code did not read the flag before the SDK finished loading. And check your logs for timeouts or certificate errors.
Troubleshooting: on in the dashboard, off for my user
Here the identity is probably not matching your rule. Confirm the identity string is the one you think it is. Confirm the traits were sent, with exactly the spelling and capitalisation the segment expects. Remember the priority ladder: a personal override beats a segment, and a segment beats the default. And confirm you changed the same environment your application is using.
Troubleshooting: changes take too long to appear
This is cache timing. List every cache between the dashboard and the user: the SDK memory cache, any shared cache you run, any CDN, and any device cache. The longest lifetime among them sets the worst-case delay. Shorten the lifetime for that flag, or provide a bypass for testers.
Troubleshooting: different answers on different servers
Two servers holding caches of different ages can disagree for a short moment. If the disagreement lasts long, check that all servers use the same environment key, the same SDK version, and the same cache settings.
Key and environment
Wrong key or wrong environment explains a surprising share of problems.
Identity and traits
Spelling, capitals, and stability decide whether rules match.
Cache lifetimes
Old answers from a forgotten cache create ghost problems.
Network path
Firewalls, proxies, and certificates can quietly block requests.
Use the identity view in the Flagsmith dashboard to see the traits stored and the flags that would be returned. It quickly tells you whether the problem is in the rules or in your application.
Real-world example: blameless postmortems
Companies such as Google and Etsy are known for blameless postmortems that begin with “what changed recently?” A visible audit trail of flag changes answers that question in seconds and keeps the review focused on learning.
22Deployment and Cloud Choices
Where the Flagsmith API runs shapes your latency, your control, and your legal comfort.
| Option | Who runs the servers | Best for | Watch out for |
|---|---|---|---|
| Hosted cloud service | The Flagsmith team | Fast start, no servers to look after | Data location and usage-based plans |
| Self-hosted in your cloud | Your team | Control over data and network placement | You own scaling, upgrades, and backups |
| Private or on-premise | Your team in your own network | Highly regulated industries | The most work, and reachability from devices |
Latency and placement
Because remote evaluation is a network call, distance matters. If your servers run in one region and the flag service runs in another continent, every uncached call pays for that journey. Place your Flagsmith endpoint, hosted or self-hosted, in the same region as the services that call it most. For a worldwide audience, rely on a distributed edge layer or run several regional instances.
What a self-hosted setup involves
You will typically run the API as several identical copies behind a load balancer, connect them to a managed database with regular backups, place a cache in front of the busiest reads, and add monitoring on request rate, errors, and latency. Spread copies across several availability zones, which are separate buildings within a region, so a single failure cannot take the service down. Practise restoring from backup, because an untested backup is another kind of hope.
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 more freedom. The house is entirely yours, including the leaking roof when it rains.
A friendly address
Put the service on a clear address under your own domain where you can. It looks professional, avoids some content blockers for browser traffic, and lets you move the service later without changing every application, because the address your code uses never has to change.
Upgrades
If you self-host, upgrade Flagsmith like any other important system. Try new versions in Staging, read the release notes, keep a rollback ready, and upgrade during a quiet period.
Real-world example: regulated industries and data location
Banks and healthcare providers often require that user-related data stays within defined regions or inside their own network. Self-hosting an open-source flag service is a common way to meet such rules while keeping modern release control.
23Experiments and Analytics with Remote Evaluation
Deciding who sees what is half the story. Learning whether the change helped is the other half.
Why remote mode suits experiments
An experiment needs three things: a fair split of users, a consistent experience for each user, and a way to link the outcome back to the variant. Remote evaluation provides the first two directly. The engine places each identity into a variant using a repeatable calculation, so a person keeps the same variant on every visit, whichever server or device handles the request. Because the decision comes from one central place, your web, mobile, and backend code all agree about which variant a person belongs to.
Linking outcomes to variants
Flagsmith decides the variant, but measuring success normally happens in your analytics tool. The practical approach is to attach the variant to every relevant event, such as “order completed”, so you can later compare groups. Flagsmith offers integrations with common analytics tools to help with this. The important habit is to record the variant at the moment the user actually experiences the difference, not merely when the request is made.
A bakery testing two recipes hands out cake with a small coloured napkin, one colour per recipe. Later, when customers return for more, the baker counts returns per napkin colour. The napkin is the variant tag attached to each event.
Good experiment habits
- Define success first. Pick the measure before you start, so you do not search for a flattering result afterwards.
- Keep a control group. A group that sees the current experience is your yardstick.
- Run through full weekly cycles. Tuesday shoppers differ from Saturday shoppers.
- Change one thing at a time. Overlapping experiments on the same screen blur the result.
- Wait for enough users. Small differences on small audiences are often luck.
If your cache ignores the identity, users can receive each other’s variants, and your experiment results become meaningless. Experiments are the strictest test of whether your cache keys are correct.
Ending an experiment cleanly
When a clear winner emerges, make its value the default for everyone, remove the losing variants and the experiment code, and archive the flag. An experiment flag is short-lived work, and it deserves the same clean-up discipline as a 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 and measuring which led more people to press play. That is a textbook multivariate experiment: one decision point, several candidate values, and a stable assignment per member.
24One Backend Serving Many Users
A server-side process handles thousands of different people, which raises questions a single phone app never faces.
One SDK instance, many identities
A phone app has one user. A backend service has thousands of users passing through at once. You should create one SDK instance when the service starts and share it across all requests, rather than creating a new one for every request. A shared instance reuses network connections and any internal caches. For each incoming request, you ask that shared instance for the flags of that request’s user.
Per-request context
At the start of each request, work out who the user is and what traits matter, ask for the flags once, and attach the result to the request’s context, the bundle of facts that travels with that request through your code. Every function that needs a flag reads it from that bundle. This gives you one network call per request at most, consistent answers within the request, and easy testing, since a test can simply supply a ready-made bundle.
A hotel front desk checks you in once, and gives you a key card. The restaurant, gym, and lift all read the same card instead of phoning the front desk each time. The flag bundle is your key card for the duration of the request.
Business customers and tenants
Many products serve other companies, called tenants. Often the flag decision depends on the company, not the individual person: “this customer has bought the analytics add-on”. A common approach is to use the company’s identifier as the identity, or to send the company’s plan and region as traits on each person’s identity. Choose the approach that matches how your rules are written, and keep it consistent across all services so every part of your product reaches the same decision.
Background jobs and queues
Jobs that run later, such as sending emails or building reports, still need decisions. The safest approach is usually to evaluate the flag when the job is created and store the result with the job, so the job behaves as the user’s experience was at that moment. Evaluating again hours later can give a different answer after a rollout change, which can confuse users who saw the earlier behaviour.
| Situation | Recommended approach | Reason |
|---|---|---|
| Web request | Fetch once, attach to request context | One call, consistent answers |
| Background job | Decide at creation, store with the job | Behaviour matches what the user saw |
| Scheduled batch over many users | Consider local evaluation | Thousands of remote calls would be slow and costly |
| Service-to-service call | Pass the decision along in the call | Both services agree and the flag service is called once |
Real-world example: request context in large platforms
Large platforms such as Google commonly attach request-scoped context, for example tracing and experiment information, to each call as it passes between services, so every service sees the same facts. Passing a flag decision along with a request follows the same discipline.
25A Safe Path From Remote to Local
If one of your services outgrows remote mode, move it with care, not with a leap.
Prove the need first
Before changing anything, gather evidence. Measure how much time flag lookups take in that service. Count how many flag requests it sends. Check whether failures of the flag service have hurt it. If the numbers are small, a short cache in the remote setup is much cheaper and safer than a mode change.
A step-by-step migration
Pick one service
Choose the service with the clearest, largest benefit. Never migrate everything at once.
Prepare the key
Store a server-side key in the service’s secrets manager, with access limited to that service.
Run both and compare
For a trial period, evaluate both ways for a sample of requests and log any difference. Disagreements reveal trait or timing problems early.
Review trait use
Check whether any feature relies on traits stored by Flagsmith in earlier remote calls, and make sure your code now sends every trait it needs with each evaluation.
Decide the refresh delay
Choose a refresh interval that matches how quickly this service must react to changes, and confirm the team accepts it.
Switch gradually
Move a small share of the service’s instances first, then more, watching latency, errors, and request volume.
Keep the way back
Leave the remote configuration available as a fast rollback until the new setup has proven stable.
What to watch afterwards
After the move, expect lookup time to fall to almost nothing and request volume to the flag service to drop sharply. Watch memory use of the service, since it now holds the rules. Watch that snapshots keep refreshing on time, and set an alert if a refresh fails repeatedly, because a service running on a very old snapshot is quietly serving old decisions. Remember that the refresh delay means a kill switch will take up to one interval to take effect in that service.
Keep your most critical kill switches visible in your incident runbook, along with a note on how long each service takes to notice a change. During an emergency, nobody should have to guess how long to wait.
Real-world example: gradual migrations at Etsy and Netflix
Both Etsy and Netflix are widely known for moving traffic between old and new systems in small, measured steps, running them side by side and comparing results before committing. Moving a service from remote to local flag evaluation deserves exactly the same patience.
26Best Practices Checklist
If you remember nothing else, remember these habits. They separate calm, boring flag usage from exciting incidents.
Setting up
- One environment per stage. Development, Staging, and Production each get their own key.
- Right key, right place. Client key on devices, server-side key in your secrets store only.
- Build a flag gateway. One module owns timeouts, caching, and defaults.
- Write the safe default for every flag and the reason behind it.
Making requests
- Fetch once per request, then read from the result.
- Always set a timeout and use a circuit breaker for repeated failures.
- Use environment-level questions for flags that do not vary by user.
- Use stable identities and keep traits small and non-sensitive.
- Use transient traits for facts you do not want stored.
Caching
- Pick lifetimes by risk. Short for critical flags, longer for cosmetic ones.
- Include the identity in every cache key.
- Consider stale-while-revalidate for smooth speed with quiet refresh.
Operating
- Watch the four signals: latency, traffic, errors, and fallback rate.
- Limit who can change Production and require approvals for sensitive flags.
- Keep an audit trail visible during incidents.
- Roll out in small steps with metrics checked between each step.
Cleaning up
- Remove the code first, then archive the flag.
- Use usage data to prove a flag is unused before deleting it.
- Review old flags monthly. Fifteen minutes of review prevents years of clutter.
Print the safe-defaults table and the troubleshooting checklist from this guide and keep them beside your runbook. At two in the morning during an incident, a clear list beats clever memory.
27Advantages, Disadvantages, and Trade-offs
No design is perfect. Remote evaluation gives you real strengths and real costs, and you should pick with open eyes.
Advantages
- Simplest setup, only a key and an SDK
- Always uses the latest rules at request time
- Rules and targeting stay private on the service side
- Works everywhere, including browsers and phones
- Can store traits and show identity views in the dashboard
- Very little logic to run or understand in your own code
- Same decision-making for every language and platform
Disadvantages
- Adds a network round trip to each uncached evaluation
- Makes your application depend on another service at run time
- Request volume grows with your traffic, with possible cost
- Caching adds freshness gaps and cache-key risks
- Needs timeouts, defaults, and failure rehearsals to be safe
- Identities and traits raise privacy duties
Key trade-offs in detail
| Trade-off | One side | Other side | How to decide |
|---|---|---|---|
| Freshness versus speed | No cache gives instant change | Long cache gives faster responses | Short for kill switches, longer for cosmetic flags |
| Simplicity versus performance | Remote mode is simple | Local mode is fastest | Start remote, move hot services to local when needed |
| Privacy versus targeting | More traits allow finer targeting | Fewer traits protect users | Send only what is truly needed, use transient traits |
| Availability versus accuracy | Fall back to defaults to keep working | Fail hard to avoid a wrong answer | Choose per flag, usually keep working |
| Control versus effort | Self-hosting gives control | Hosted gives low effort | Match to your data rules and team size |
Thinking in CAP terms
When the network between your application and the flag service breaks, you must choose between staying available with a possibly old answer and refusing to answer until you can be sure. Flag systems nearly always favour staying available, because an application that keeps working with a slightly old flag is better than one that stops. That is why defaults and last-known-good values are central to a safe design.
Real-world example: Amazon and availability first
Amazon’s engineers have often explained that for many customer-facing features it is better to keep serving, even with slightly stale data, than to fail. A flag lookup that falls back gracefully follows the same principle.
28Putting It All Together: A Full Story
Let us watch every idea from this guide work together in one realistic example.
The scenario
FreshCart, a fictional online grocery company, runs a website, phone apps, and a family of backend services serving several million people. The team has built a new delivery-slot picker and wants to release it carefully. They use Flagsmith. Their website and apps use client-side SDKs, which always evaluate remotely. Their backend services use server-side SDKs, which start in remote mode.
The journey
Prepare
They create the flag with a clear name and owner. Defaults are off everywhere, and the safe default inside the code is also off.
Build a gateway
Their backend gets a small flag module with a short timeout, a thirty-second shared cache keyed by identity, and a circuit breaker.
Decide once
The order service evaluates the flag once per request and includes the decision in its response, so the website and the apps always agree with the server.
Dark launch and staff first
The code ships with the flag off, and a staff segment turns it on. Employees place real orders for several days.
Ramp
A percentage rule releases the feature to five percent of customers, then ten, then twenty-five. The team watches order errors, speed, and completed deliveries between each step.
A hiccup
During the ramp, the flag service has a short blip. The gateway’s circuit breaker opens, and the order service uses last-known answers. Customers notice nothing. An alert on the fallback rate pages the team, who confirm the blip and see recovery within minutes.
Performance review
After release, the team notices that their busiest pricing service spends a lot of time on flag lookups. They move that one service to local evaluation, protect its server-side key in the secrets manager, and accept a one-minute refresh delay for it.
Clean up
After two stable weeks at full release, the old slot picker is deleted, the flag is archived, and the monthly review confirms it is gone.
What made it work
Every layer did its job. A gateway kept timeouts, caching, and defaults in one place. Stable identities kept users in consistent buckets. Remote evaluation kept the rules private and the setup simple. A circuit breaker and safe defaults made a short outage invisible. Server-side decisions kept money logic honest. And a measured move to local evaluation fixed the one hot spot without disturbing anything else.
Real-world example: Slack and gradual feature rollouts
Collaboration tools like Slack introduce major interface changes to a limited audience first, learn from feedback, and widen the audience over time. This pattern, visible whenever a new interface appears for some workspaces before others, relies on the same server-controlled, per-user decision that remote evaluation provides.
29Plain-English Glossary
A quick reference for every important word used in this guide.
| Term | What it means |
|---|---|
| Evaluation | Turning a flag’s rules plus one specific user into a single final answer for that user. |
| Remote evaluation | Evaluation done on Flagsmith’s servers, with only finished answers sent to your application. |
| Local evaluation | Evaluation done inside your own server process using a downloaded copy of the environment’s rules. |
| Environment document | The full snapshot of an environment’s features, segments, and overrides used by local evaluation. |
| Environment | A separate copy of your flag settings, such as Development, Staging, or Production. |
| Client-side key | A public identifier safe to place in apps and pages, allowing reads of flags only. |
| Server-side key | A private credential that belongs only in your backend’s secret storage. |
| Feature | The named item you control, with an enabled state and an optional value. |
| Remote config | A value, such as a number or text, that a feature carries and that you can change without a release. |
| Identity | A stable label for one user, used to give consistent personalised answers. |
| Trait | A small fact about an identity, such as plan or country, used by segment rules. |
| Transient trait | A trait used for one evaluation only and not stored afterwards. |
| Segment | A saved group of users defined by rules over traits. |
| Override | A rule that replaces the default value for a segment or a single identity. |
| Multivariate flag | A flag with several values split across users by percentage. |
| Priority ladder | The order of precedence: identity override, then segment override, then environment default. |
| Round trip | The journey of a request to a service and its answer back, whose time is the main cost of remote mode. |
| Timeout | The longest your code will wait for an answer before giving up. |
| Back-off and jitter | Waiting longer after each failure, with a small random delay so callers do not all retry at once. |
| Circuit breaker | A guard that stops calling a failing service for a while and uses a fallback instead. |
| Safe default | The value used when no real answer can be obtained, chosen for safety. |
| Stale-while-revalidate | Serving a slightly old cached answer immediately while fetching a fresh one in the background. |
| Eventual consistency | The idea that caches may briefly disagree but all converge on the latest value. |
| Flag gateway | A small module in your code that owns all flag lookups, timeouts, caching, and defaults. |
| Kill switch | A long-lived flag that disables a costly or risky capability instantly during an incident. |
| Audit log | A record of who changed which flag and when. |
30Frequently Asked Questions
Short answers to the questions people ask most often about remote evaluation.
31Summary and Key Takeaways
Remote evaluation lets a small, simple caller ask a powerful central brain for finished decisions.
You began with a simple problem: your application must decide, for each user, which features to show. Flagsmith’s answer, in its default mode, is to keep the rules and the decision-making on its own servers and send back only the finished answers. That choice is the source of both its greatest strengths, which are simplicity, privacy of rules, and always-current decisions, and its main costs, which are a network trip and a runtime dependency. Everything else in this guide is about getting the strengths while managing the costs.
Key Takeaways
- Evaluation is the act of turning rules plus one user into one answer. In remote mode it happens on Flagsmith’s servers, and only the finished answers return to your code.
- Remote mode is the default and the only mode for browsers and phones. Server-side SDKs can optionally switch to local evaluation using a secret key.
- The priority ladder is fixed. A personal override beats a segment override, which beats the environment default, and percentage splits are stable for each identity.
- The real cost is the network round trip. Fetch all flags once per request, set timeouts, reuse connections, and never call the service inside a loop.
- Plan for failure. Use safe defaults, last-known-good values, retries with back-off and jitter, and a circuit breaker, then rehearse an outage.
- Cache by risk and include the identity in every cache key. Short lifetimes for kill switches, longer ones for cosmetic flags, and never share personalised answers between users.
- Consider local evaluation only for hot, trusted backend services. Accept a refresh delay and protect the server-side key, and keep remote mode everywhere else.