Server-Side SDK in Flagsmith

Server-Side SDK in Flagsmith

A complete, plain-English guide to how the Flagsmith server-side SDK works inside your backend: remote and local evaluation, the flag engine, failure handling, security, scaling, and the habits that keep production calm.

Picture a busy Friday evening. Your team shipped a shiny new recommendation engine at noon, and for a few hours everything looked fine. Then the support queue starts to fill. The new engine is slow for users in one region, and every page that depends on it is crawling. The old way of fixing this is painful: write a patch, run the tests, wait for the build, redeploy every server, and hope nothing else breaks on the way. That can take an hour. Meanwhile, customers are leaving.

Now picture a different Friday. The new engine was wrapped in a feature flag from the start. Someone opens a dashboard, flips one switch to “off”, and within a minute every server in your fleet quietly goes back to the old engine. No build. No deploy. No panic. The thing that makes this possible inside your backend code is a small library called the server-side SDK.

This guide teaches you exactly how that library works in Flagsmith, one of the most popular open-source feature flag platforms. You will learn what it talks to, how it decides what each user should see, how fast it is, what happens when things break, and how to use it safely at scale. No code is needed to follow along. Every new word is explained the first time it appears, and every big idea comes with an everyday comparison.

AWhy Backend Services Need Feature Flags

Before we open the SDK, we need to understand the problem it solves: separating “the code is on the server” from “users can see the feature”.

What is a feature flag?

A feature flag (also called a feature toggle) is a named switch that your code checks before deciding what to do. If the switch is on, the code runs the new behaviour. If it is off, the code runs the old behaviour. The important part is that the switch lives outside your code, in a place you can change at any time without rebuilding or redeploying anything.

A flag can be as simple as “on or off”. It can also carry a small piece of information, such as a number, a word, or a short piece of text. Flagsmith calls these remote config values. For example, a flag named “max_upload_size” could carry the number 25, and you could later change it to 50 from the dashboard without touching a single line of code.

Everyday analogy

Think of a house with a wall switch for the living room light. Without the switch, the only way to turn the light off is to open the wall and cut the wires. That is what shipping a code change is like. A feature flag is the wall switch. The wiring (your code) stays untouched, and anyone with access to the switch can change the result in a second.

Deploying is not the same as releasing

This is the single most important idea in the whole topic. Deploying means copying new code onto your servers. Releasing means letting real users experience what that code does. Without flags, these two things happen at the same moment, so every deployment is a small gamble. With flags, you deploy the code hidden behind an “off” switch, check that the deployment itself is healthy, and then release the feature slowly: first to your own team, then to one percent of users, then ten percent, then everyone.

Large engineering teams rely on this style of working. Facebook has described an internal system called Gatekeeper that lets engineers expose a change to a chosen slice of users. Etsy became well known for deploying to production dozens of times per day, using configuration flags to keep unfinished work invisible. The practice is common because it turns risky big-bang launches into a series of small, reversible steps.

So what is Flagsmith?

Flagsmith is a feature flag and remote configuration platform. It is open source, which means you can read its code and run it yourself on your own infrastructure. It is also offered as a hosted service, called Flagsmith Cloud, if you prefer not to run anything. Either way, you get a web dashboard where people create flags and decide who sees what, plus an API and a set of libraries that your applications use to read those decisions.

What is an SDK, and what makes it “server-side”?

An SDK (software development kit) is a ready-made library that you add to your project so you do not have to write all the plumbing yourself. The Flagsmith SDK knows how to authenticate, how to ask for flags, how to understand the answers, and what to do when something goes wrong. You simply ask it a question like “is this feature on for this user?” and it hands back an answer.

The word server-side means the SDK runs inside code that you control and that users cannot inspect: a web API, a background worker, a scheduled job, a microservice. The opposite, client-side, means code that runs on the user’s own device, such as a web browser or a phone app. This difference sounds small, but it changes almost everything about how the SDK is designed, which is why the rest of this guide is devoted to it.

2
evaluation modes: remote and local
60 s
typical default refresh interval in local mode
1
secret server-side key per environment (at minimum)
i
Good to know

Flagsmith publishes server-side SDKs for many popular languages, including Python, Node.js, Java, .NET, Go, Ruby, PHP, Rust, and Elixir. The names of methods and settings differ slightly between languages, but the ideas in this guide apply to all of them. Always check the official documentation for your language before you copy any setting name.

BThe Core Vocabulary You Need

Flagsmith uses a handful of building blocks. Once these eight words feel familiar, everything else in the SDK will make sense.

Flagsmith organises everything in a simple hierarchy. At the top sits your organisation (your company). Inside it you create projects, usually one per product or application. Inside each project you create environments, such as development, staging, and production. Inside each environment live your features. The big benefit of this layout is that the same flag can be on in development and off in production, with no risk of the two affecting each other.

Structure

Environment

A separate copy of your flag settings for one stage of life, like development or production. Each environment has its own keys, so a mistake in one never leaks into another.

Building block

Feature

The named thing you control. It can be a simple on/off flag, a remote config value, or both at once. Its name is what your code asks for.

Value

Remote config

A small piece of data attached to a feature, such as a number or a short word. It lets you tune behaviour (a limit, a message, a threshold) without redeploying.

Who

Identity

A unique label for the person or thing you are asking about, such as a user ID, an account ID, or a tenant name. Flagsmith uses it to give the same answer to the same identity every time.

Facts

Trait

A piece of information about an identity, like their plan, country, or app version. Traits are the facts that segment rules look at.

Group

Segment

A saved group of identities defined by rules, for example “plan equals enterprise” or “country is Germany”. You can give a segment its own flag values.

Experiment

Multivariate option

Several possible values for one feature, each given a percentage share. It is how you run an A/B/C test, where 50 percent see one value and 25 percent see each of two others.

Exception

Override

A special rule that beats the normal one. An identity override gives one specific identity a custom value, such as a beta tester who always sees the new screen.

Everyday analogy

Imagine a cinema with several screens. Each environment is a different building (rehearsal hall, preview theatre, main theatre). A feature is a film. An identity is one ticket holder. Traits are the facts printed on the ticket, like age category and membership level. A segment is the VIP queue, defined by a rule on those facts. An override is the manager waving one particular guest through, no questions asked.

Why identity matters so much

Imagine you want to show a new checkout page to exactly 10 percent of users. If every request was decided by a random coin flip, the same person could see the new page in the morning and the old page in the afternoon. That is confusing and makes testing meaningless. Flagsmith avoids this by turning the identity into a stable number using a hashing method, then checking whether that number falls inside the chosen percentage. The same identity always lands on the same side. We will look at this more closely in the chapter on how evaluation works.

i
Remember

If you ask for flags without giving an identity, you get the environment-wide defaults. You cannot use segments, identity overrides, or percentage-based rollouts without an identity, because there is nobody to look up and nothing to hash.

On/off flag or remote config value?

A common beginner question is when to use a plain on/off flag and when to use a value. Use an on/off flag when the question is “should this behaviour happen at all?” Examples are showing a new page, enabling a new payment route, or switching on a background job. Use a remote config value when the question is “how much, how often, or which one?” Examples are the number of items per page, the retry limit for a partner service, or the name of the search provider to call. Many features use both: the flag says whether the new behaviour is active, and the value tunes it.

Values deserve discipline. Keep them small, since they travel with every document or response. Give them clear units in the name, such as “timeout_seconds” rather than just “timeout”, so that nobody enters 5000 thinking of milliseconds when the code expects seconds. Validate them in your code, with sensible minimum and maximum limits, because a typing mistake in a dashboard should never be able to turn a ten-second timeout into ten hours.

CServer-Side vs Client-Side SDKs

Flagsmith ships two families of SDKs. Knowing which family you are holding, and why they differ, prevents the most serious mistake people make.

Client-side SDKs run in places you do not control. A browser tab can be opened by anyone, and anyone can press a key and look at everything inside it. A mobile app can be taken apart by a curious person with the right tools. Because of that, a client-side SDK must be built on one assumption: everything it knows can become public. It therefore uses a public identifier called the client-side environment ID, and it only asks the server one narrow question at a time: “what are the flags for this one identity?”

Server-side SDKs live in a trusted place. Nobody can open your data centre or your container and read what is in memory. This trust allows the SDK to use a server-side environment key, which is a secret. A secret key unlocks extra abilities, in particular the ability to download the complete rulebook for an environment and evaluate it yourself. That ability is the foundation of local evaluation, which we will study in detail soon.

QuestionClient-side SDKServer-side SDK
Where does it run?Browsers and mobile appsBackend services, workers, and jobs
Which key does it use?Client-side environment ID (public)Server-side environment key (secret)
Can the key be seen by users?Yes, by designNever. Treat it like a password
How are flags decided?The server decides and sends back the resultThe server decides remotely, or the SDK decides locally
Is local evaluation possible?NoYes
How many identities per process?Usually one (the current user)Thousands, one per incoming request
Main design goalShow the right screen to one personMake fast decisions for many people, safely

Why the rulebook must stay secret

The downloadable rulebook, called the environment document, contains every segment rule, every percentage split, and every identity override in the environment. If it reached a browser, a curious user could learn how your pricing tiers are targeted, which beta testers exist, and which unreleased features are waiting in the wings. That is why only the secret key can fetch it, and why the secret key must never be placed in front-end code.

!
Warning

The most common serious mistake is pasting a server-side key into a web page, a mobile app, or a public code repository. Anyone who finds it can download your complete targeting rules. If that ever happens, delete the key in the dashboard and create a new one immediately. Flagsmith lets you hold more than one server-side key per environment, so you can rotate keys without downtime.

Why server-side is powerful

  • Can evaluate flags in memory with no network call
  • Sees the whole rulebook, so complex rules just work
  • Protects your business logic from prying eyes
  • Controls what the user is allowed to do, not just what they see

What you must watch

  • A leaked key exposes the entire environment
  • Many processes means many sets of connections to manage
  • You are responsible for timeouts and fallbacks
  • Long-running processes can hold stale rules if refresh fails

A practical rule of thumb helps here: use the server-side SDK whenever a decision protects something valuable, such as access to a paid feature, a data export, or a risky operation. Flags in the browser only change what the user sees. Flags on the server change what the user is allowed to do. Never rely on a client-side flag alone to guard something that matters.

DArchitecture and Components

Here is the full picture of the parts that cooperate every time your backend asks a question about a flag.

Let us walk through the diagram below from left to right. An engineer works in the Flagsmith dashboard, a web interface, to create flags and change them. The dashboard saves changes through the Flagsmith API, which stores them in a primary database. The platform also keeps a fast, read-optimised copy of each environment ready for the SDKs to use. On Flagsmith Cloud this fast path is called the Edge API, a globally distributed service built so that flag reads stay quick even for customers far from any single data centre. If you self-host, you run the API yourself and can place it close to your own services.

flowchart LR
  Dev["Engineer using the Dashboard"] --> API["Flagsmith API"]
  API --> DB[("Primary Database")]
  API --> Edge["Edge API and cached environment data"]
  Users["End Users"] --> GW["API Gateway"]
  GW --> LB["Load Balancer"]
  subgraph Platform["Your Backend Platform"]
    LB --> S1["Service Instance 1 with SDK"]
    LB --> S2["Service Instance 2 with SDK"]
    LB --> S3["Service Instance 3 with SDK"]
  end
  S1 --> Edge
  S2 --> Edge
  S3 --> Edge
Figure 1 — Every service instance holds its own SDK client, which talks to Flagsmith independently.

On the right side of the picture sits your platform. Real users reach you through an API gateway (the front door that handles authentication and routing), which hands requests to a load balancer (the traffic officer that spreads requests across identical copies of your service). Each copy of your service contains its own Flagsmith SDK client. Notice something important: there is no shared “flag server” inside your platform. Each instance fends for itself, which makes the design simple and removes a central point of failure.

The parts inside the SDK

Core

Client object

The main handle you create once at startup. You ask it for environment-wide flags or flags for one identity. It owns the configuration, the HTTP connection, and any background work.

Core

Flags collection

What comes back from a request: a bundle of flags you can query by name. Each flag carries an enabled state and an optional value.

Local mode

Environment document

The full rulebook for one environment, downloaded as a single document and kept in memory. It lists features, segments, rules, and overrides.

Local mode

Flag engine

A shared piece of logic, implemented across languages, that reads the environment document and works out the answer for an identity. Because every SDK uses the same rules, a Python service and a Java service agree.

Safety

Default flag handler

Your own fallback rule. If Flagsmith cannot be reached, or a flag does not exist, the handler decides what to return instead of letting the request fail.

Insight

Analytics reporter

An optional helper that counts how often each flag is evaluated and reports those counts in batches, so the dashboard can show which flags are alive and which are forgotten.

Everyday analogy

Think of a chain of bakeries. Head office (the dashboard and API) writes the recipe book. Each bakery (a service instance) has an assistant (the SDK) who either phones head office every time a customer asks for a recipe (remote evaluation) or keeps a photocopy of the whole book on the counter and checks it for free (local evaluation). Either way, the customer gets a consistent loaf, and head office never has to be in the shop.

Two more supporting parts are worth knowing about. Webhooks let Flagsmith notify other systems when a flag changes, which is handy for audit trails and chat alerts. And an optional piece called the Edge Proxy can sit inside your own network, caching environment data close to your services, which we will revisit when we compare ways of running the SDK.

ERemote Evaluation: Asking Flagsmith Every Time

Remote evaluation is the default way the server-side SDK works. It is the simplest to understand, so it is the right place to start.

In remote evaluation, Flagsmith does the thinking. Your service sends a question across the internet, Flagsmith applies all the rules, and the answer comes back ready to use. Your SDK never sees the rulebook. It only sees the final result for the identity you asked about. This is similar to calling a help desk: you describe who you are, they look up the rules, and they tell you what you are allowed to do.

sequenceDiagram
  autonumber
  participant U as End User
  participant S as Your Service
  participant K as Flagsmith SDK
  participant F as Flagsmith Edge API
  U->>S: Request arrives
  S->>K: Ask for flags for this identity
  K->>F: HTTPS call with server key, identity and traits
  F->>F: Apply overrides, segments and variants
  F-->>K: Flags and values for this identity
  K-->>S: Flag results
  S-->>U: Response shaped by the flags
Figure 2 — One round trip to Flagsmith for every flag lookup in remote mode.

Two kinds of questions

The SDK can ask two different questions. The first is “what are the flags for the environment as a whole?” The answer reflects the default settings and does not depend on any person. The second is “what are the flags for this identity, given these traits?” The answer reflects overrides, segments, and any percentage-based decisions. Most real applications use the second question, because most real decisions depend on who is asking.

1

Your code asks

A request arrives and your code asks the SDK for flags, passing an identity label and optionally a few traits such as plan or country.

2

The SDK calls the API

The SDK builds a secure HTTPS request that includes the secret environment key in a header. This proves who you are and which environment you mean.

3

Flagsmith evaluates

The server looks up the identity (creating it if it is new), saves any traits you sent, then works through overrides, segments, and variants.

4

The answer returns

The reply lists every feature with its enabled state and value. The SDK wraps it in a friendly collection.

5

Your code decides

You ask the collection whether a named feature is enabled or what its value is, and branch your logic accordingly.

i
Side effect to know

In remote mode, sending an identity with traits normally stores that identity and those traits inside Flagsmith, so they can be used for segments later. That is useful, but it also means you are sharing data about your users with the platform. Send only what you need. Newer SDKs also offer a way to mark traits or identities as transient, so they are used for the decision but not saved.

Doing the maths on remote calls

Remote evaluation is wonderfully simple, but every lookup costs a network round trip. A typical call may take tens of milliseconds, and more if your servers are far from the nearest Flagsmith endpoint. That is fine for a handful of lookups. It becomes a problem at scale. Suppose a service handles 5,000 requests per second and each request checks 2 flags. If nothing is reused, that is 10,000 calls per second to Flagsmith. Over a day, that is about 864 million calls. Most of them would ask almost the same question and get almost the same answer.

Cost matters too. On a hosted plan, usage is generally measured in API requests, so remote lookups at that rate can be expensive and may hit rate limits. This is exactly why Flagsmith offers a second mode, and why high-traffic services almost always use it.

Where remote shines

  • Easiest possible setup: add the key and go
  • Always reflects the very latest dashboard change
  • Small memory footprint in your service
  • Traits and identities are saved and reusable in segments
  • Works well in short-lived or serverless environments

Where remote hurts

  • Adds network latency to the request path
  • Volume of calls grows with traffic
  • Your feature behaviour depends on a network being available
  • Each lookup uses part of your API request allowance
i
Tip

Even in remote mode, ask for flags once per incoming request and pass the result down to the functions that need it, rather than calling the SDK again in every function. One lookup per request instead of ten is an easy and large saving.

Timeouts and retries in remote mode

Remote evaluation puts a network call on your request path, so the timeout setting becomes a promise to your users. Imagine your service promises a response in one second. If the flag call is allowed to wait ten seconds, a slow Flagsmith can break that promise for every single request. Set the timeout to a small fraction of your overall budget, such as a few hundred milliseconds, and choose a default flag handler that gives safe behaviour when the timeout fires.

Retries need the same care. One quick retry can rescue a request from a momentary network glitch. Several retries, each with its own long timeout, can multiply the delay: three attempts of two seconds each means a six-second wait before the fallback even starts. A good rule is that the total time of all attempts must still fit inside the time you are willing to spend on a flag decision. When in doubt, fail fast and fall back.

FLocal Evaluation: Keeping a Copy of the Rulebook

Local evaluation flips the model. Instead of asking Flagsmith for answers, your service downloads the questions and the rules, and answers by itself.

When local evaluation is switched on, the SDK downloads the environment document from Flagsmith when it starts. This is one compact package describing every feature, its default state, every segment and its rules, every percentage split, and every identity override for the environment. The SDK keeps it in memory. From then on, when your code asks “what are the flags for identity 42?”, the SDK runs the shared flag engine against that in-memory document. No network call happens. The answer arrives in a tiny fraction of a millisecond.

flowchart TD
  Boot["Service starts"] --> Fetch["SDK downloads the environment document"]
  Fetch --> Mem["Document held in memory"]
  Mem --> Req["A request needs a flag"]
  Req --> Eng["Local flag engine evaluates the rules"]
  Eng --> Ans["Answer returned in microseconds"]
  Mem --> Timer["Refresh timer fires on a schedule"]
  Timer --> Fetch2["Download a fresh document"]
  Fetch2 --> Swap["Replace the old document with the new one"]
  Swap --> Mem
Figure 3 — Local evaluation: requests read from memory while a timer keeps the copy fresh.

Staying fresh: the refresh interval

A photocopy goes out of date the moment the original changes. To handle this, the SDK runs a small background task that downloads a new copy of the document on a fixed schedule. The default is usually every 60 seconds, and you can change it. When a fresh document arrives, the SDK swaps it in as a whole, so a request in progress never sees a half-updated rulebook. In practice this means a dashboard change reaches every service within about one refresh interval plus a little caching time.

Everyday analogy

A taxi driver can phone the dispatcher for every road closure (remote) or keep a printed map in the cab and receive a new printed map every minute by courier (local). The printed map is instantly readable, works in a tunnel with no signal, and is only ever a minute out of date. For a driver making hundreds of decisions per hour, the printed map wins easily.

What local evaluation gives you

Speed

Microsecond decisions

Reading from memory is vastly faster than any network call, so flag checks stop being a meaningful part of your response time.

Cost

Predictable traffic

Traffic to Flagsmith depends on how many service instances you run and how often they refresh, not on how many users you have.

Resilience

Survives outages

If Flagsmith becomes unreachable, the last good document keeps working. Decisions continue, only slightly out of date.

Isolation

Fewer moving parts per request

A user request no longer waits on an external service, so a slow Flagsmith cannot slow your users.

The honest limitations

Local evaluation is powerful, but it is not magic. Because the SDK is deciding on its own, there is no server-side identity record being consulted for each request. That has consequences you should know before you choose it.

First, traits are not saved by the decision itself. In local mode, the traits you pass are used for that one evaluation and then forgotten; they do not become stored data in Flagsmith the way they would in remote mode. If you rely on traits previously stored on an identity, you must pass them in yourself each time. Second, the document must be small enough to hold and download comfortably. Very large environments with huge numbers of segments or overrides produce bigger documents, which take more memory and time on every refresh. Third, the SDK needs a background task to keep refreshing, which is easy in a long-running web service but awkward in environments that freeze or destroy processes between requests. Finally, support for some newer features, such as identity overrides in local mode, depends on the SDK version, so check the release notes for your language.

!
Watch out

A service that cannot download the first document has nothing to evaluate against. Decide what your service should do in that case: wait and retry, fail the startup, or fall back to safe defaults. Never leave this to chance.

GChoosing Your Mode: Remote, Local, Edge Proxy, or Offline

There is no single best way to run the SDK. The right choice depends on your traffic, your runtime, and how much staleness you can tolerate.

Besides plain remote and plain local evaluation, two other arrangements deserve attention. The Edge Proxy is a small service you run inside your own network. It holds cached environment data and answers SDK requests on behalf of Flagsmith, so your services talk to something nearby and fast. It also reduces the load on the main Flagsmith API. It is distributed as a container image, so it fits neatly into existing container platforms; check the current documentation for which plans include it. The second arrangement is offline mode. Here the SDK never calls Flagsmith at all. Instead, it reads an environment document from a file you provide. This suits locked-down networks, test suites, and emergency fallbacks.

OptionFreshnessSpeed per lookupDepends on network per request?Best for
Remote evaluationImmediateNetwork round tripYesSmall services, serverless, low traffic
Local evaluationWithin one refresh intervalIn-memory, very fastNoHigh-traffic, long-running services
SDK through Edge ProxyNear immediate, cachedFast local hopYes, but nearbyLarge fleets wanting low latency and less upstream load
Offline modeOnly as fresh as the fileIn-memory, very fastNoAir-gapped systems, tests, disaster fallback

A simple way to decide

Scenario 1: A web API with steady, heavy traffic

A product catalogue API runs on twenty containers and serves thousands of requests per second. Choose local evaluation. Lookups become nearly free, traffic to Flagsmith stays tiny, and a short Flagsmith outage goes unnoticed.

Scenario 2: A serverless function that runs a few times an hour

A scheduled job wakes up, does some work, and disappears. A background refresher has no time to live. Choose remote evaluation, or place an Edge Proxy in front if the extra latency matters.

Scenario 3: A service in a network with no outbound internet

A regulated system cannot reach the public internet. Either self-host Flagsmith inside the network and point the SDK at it, or use offline mode with an environment document delivered as part of your release process.

Scenario 4: An experiment that needs instant switch-off

If a feature is dangerous and you must be able to disable it in seconds, local evaluation with a short refresh interval is usually enough. Lower the interval carefully, because more frequent refreshes mean more traffic from every instance.

Fast and slightly stale, or slow and perfectly fresh: every flag system asks you to pick a point on that line.

Counting the refresh traffic

Local evaluation does generate its own traffic, so it helps to do the arithmetic. If you run 1,000 service instances and each refreshes once every 60 seconds, that is 1,000 downloads per minute, or roughly 17 per second, which adds up to about 1.44 million per day. This is a tiny and predictable number compared with the billions of calls that remote evaluation could produce, and it does not grow when your user count grows. If you shorten the interval to 10 seconds, the figure becomes six times larger, so make that change deliberately.

HHow a Flag Is Actually Decided

Whether the decision happens on Flagsmith’s servers or inside your SDK, the same ordered set of rules is used. Understanding the order explains every surprising result you will ever meet.

Flagsmith checks possible answers from the most specific to the most general, and it stops at the first match. There are three layers. The most specific layer is an identity override, a value set for one exact identity. If one exists, it wins, no matter what any other rule says. If there is no override, Flagsmith looks at segments. If the identity belongs to a segment that has its own value for this feature, that value is used. When the identity belongs to several such segments, the one with the highest priority in the list wins. If no segment applies, the environment default is used, and if the feature has multivariate options, the identity is placed into one of them by percentage.

flowchart TD
  A["Flag requested for an identity"] --> B{"Identity override exists?"}
  B -- Yes --> R1["Use the identity override value"]
  B -- No --> C{"Identity matches a segment with its own value?"}
  C -- Yes --> R2["Use the value from the highest priority matching segment"]
  C -- No --> D{"Feature has multivariate options?"}
  D -- Yes --> R3["Hash the identity into a bucket and pick a variant"]
  D -- No --> R4["Use the environment default value"]
Figure 4 — The order of decision: override, then segment, then variant or default.
Everyday analogy

Think of airport security. A person with a personal diplomatic pass walks straight through (identity override). Someone with a frequent flyer card uses the priority lane (segment). Everyone else follows the general queue rules (environment default). The officer always checks for the most specific pass first and stops as soon as one is found.

How segments find their members

A segment is a list of rules, and each rule holds conditions built from traits. A condition might say “trait country equals Germany” or “trait app_version is greater than 4.2” or “trait email contains example.com”. Rules can be combined, so that an identity must satisfy all conditions in one rule, or any one of several rules. Because the conditions read traits, the traits you pass (or have stored) decide membership. If you forget to supply a trait, a rule that depends on it simply does not match, which is a common reason why “the segment is not working”.

The magic of stable percentages

A percentage split must give the same answer to the same identity every time, otherwise nobody could trust it. Flagsmith achieves this by running a hash function on the identity combined with an identifier for the feature or segment. A hash function is a recipe that turns any piece of text into a number that looks random but is always the same for the same text. The result is turned into a position between 0 and 100. If your rollout is set to 20 percent, identities landing below 20 are in, and the rest are out.

Two lovely properties follow. First, raising the percentage from 20 to 30 keeps the original 20 percent in and only adds new people, so nobody who already saw the feature loses it. Second, because the feature or segment is mixed into the hash, the same users are not always the “first 10 percent” for every experiment, which keeps your experiments independent of each other.

i
Tip

Multivariate options without an identity cannot be split by percentage, because there is nobody to hash. In that situation the environment default is used. If your A/B test seems to give everyone the same answer, check that you are passing an identity.

IAdvanced Design: Traits, Segments and Variants in Depth

Once the basics feel comfortable, the quality of your targeting depends on how thoughtfully you design the facts you send and the groups you build from them.

Designing traits like a data model

Traits are the raw material of every segment, so they deserve the same care as a database table. Choose a small, stable vocabulary and write it down. For each trait, decide its name, its type, the values it may hold, and which service is responsible for supplying it. A trait named “plan” with the values “free”, “pro”, and “enterprise” is clear and easy to target. A trait named “user_type_2” with unexplained numbers is a future headache. Keep names lower case and consistent, because a segment that looks for “Plan” will quietly fail to match a trait called “plan”.

Prefer coarse facts over precise ones. A segment rarely needs a full birth date; an age band is enough. It rarely needs an exact street address; a country or region is enough. Coarse traits are safer for privacy, smaller to move around, and more stable over time. They also make segments easier to explain to colleagues, which matters when a product manager asks why a certain customer saw a certain screen.

Everyday analogy

Think of a library membership card. The librarian does not need your full life story to decide whether you may borrow a rare book. A few clear facts, such as membership level and whether fines are unpaid, are enough. Good traits work the same way: a handful of clear facts that rules can read quickly and that nobody would be embarrassed to see printed on a card.

Building segments that stay understandable

A segment is a promise: “these are the people I mean”. If you cannot say that promise in one sentence, the segment is too complicated. “Customers on the enterprise plan in Europe” is a good promise. “People who are on plan A or B but not in region C unless their account is older than a year, except on Thursdays” is a bug waiting to happen. When a rule list grows long, split it into several smaller segments with clear names, then combine them through the priority order of the feature.

Habit

Name by meaning

Call a segment “internal staff” or “enterprise customers”, not “segment 7”. Anyone reading the dashboard should understand it without asking.

Habit

Keep rules few

Aim for one to three conditions per segment. Each extra condition is another place for a missing trait to break the match.

Habit

Order by specificity

Place narrow, high-importance segments above broad ones, because the higher segment wins when an identity belongs to both.

Habit

Reuse segments

Segments belong to a project, so one “beta testers” segment can serve many features, and fixing its membership fixes them all at once.

Percentages and variants without surprises

When you run an experiment with several variants, give each variant a share and make sure the shares add up as you intend. Suppose a feature offers a control value at 50 percent, variant A at 25 percent, and variant B at 25 percent. Each identity lands in exactly one bucket, and because the placement is stable, the same person sees the same version on every visit. This is important for fair measurement. If people drifted between versions, you could never tell which version caused a change in behaviour.

Be careful when you change shares during an experiment. Moving a variant from 25 to 40 percent moves some identities from one bucket to another, which can contaminate your results. If you must adjust, record the date, and analyse the periods before and after separately. For safety rollouts rather than experiments, changing percentages is normal and expected, and the stable hashing ensures that people who already have the feature keep it as the percentage climbs.

i
Tip

Write down, next to each experiment, the question it answers, the metric that will decide it, and the date you will stop it. Experiments without an end date turn into permanent, untested forks in your product.

Identity choice: who is the “who”?

The identity you pass decides the unit of consistency. If you use a user ID, each person is treated individually. If you use an account or tenant ID, every user inside one company sees the same thing, which is exactly what you want for features that affect shared data, such as a new reporting engine or a changed billing screen. If you use a session ID, the same person may see different things on different visits, which is rarely wanted except for short-lived tests. Decide on purpose, and keep the choice consistent across all your services, or two services will disagree about the same customer.

Choosing between a user and an account

A project management tool wants to roll out a new board layout. If it targets individual users, two colleagues on the same team may see different layouts and be unable to follow each other’s instructions. If it targets the account identity instead, the whole team sees the same layout together. The flag is identical; only the identity changed, and the experience improved.

!
Warning

Never use a value that changes over time as an identity, such as a temporary token or a rotating cookie. The percentage hash will see a new person every time, and users will see flickering behaviour. Use something permanent that your own systems already trust.

JData Flow: The Life of a Flag Change

Follow a single click in the dashboard all the way to a changed behaviour inside your running service, and learn where the delays hide.

Imagine an engineer turns off a misbehaving feature. Several things happen in order. The dashboard sends the change to the Flagsmith API. The API saves it to the database and writes an entry in the audit log, a permanent record of who changed what and when. It then publishes updated environment data to the fast read path, so SDKs and the Edge API see the new truth. Finally, each of your service instances picks up the new rules the next time it asks. In remote mode that is the very next lookup. In local mode it is the next scheduled refresh.

sequenceDiagram
  participant E as Engineer
  participant D as Dashboard
  participant A as Flagsmith API
  participant C as Edge Cache
  participant K as SDK Refresher
  participant S as Your Service
  E->>D: Turns the feature off
  D->>A: Save the change
  A->>A: Write to database and audit log
  A->>C: Publish updated environment data
  A-->>E: Change confirmed
  K->>C: Scheduled refresh asks for the document
  C-->>K: Fresh document
  K->>K: Swap the document in memory
  S->>K: Next flag check
  K-->>S: Feature is now off
Figure 5 — A dashboard change travels to the SDK in local mode.

Adding up the delay

The time between a click and a changed behaviour is the sum of a few small pieces: the time to save and publish the change (usually brief), any caching on the read path (short), and the wait until your SDK next refreshes (up to one full interval). With a 60 second interval, the worst case is a little over a minute. With a 15 second interval it is a little over fifteen seconds. If a feature is dangerous, plan your kill switch around this number, not around the moment of the click.

0 to 60 s
average wait for the next refresh at the default interval
1 request
should read flags only once, then pass the result along
All or nothing
each refresh swaps the whole document, never a half update

A word about consistency

Because each service instance refreshes on its own timer, two instances can briefly disagree. For a few seconds, instance A may already know the feature is off while instance B still thinks it is on. For many features this does not matter. For features that span several steps, such as a checkout that touches three services, it can. The safe habit is to decide once at the front door of a user journey and pass that decision along with the request, for example in a header or a field in a message, instead of letting every service decide again on its own.

Everyday analogy

A school sends out a new timetable. Every classroom gets a printed copy, but the copies arrive at slightly different moments. For a minute or two, one class may follow the old bell while the next follows the new one. The school fixes this for important events (like exams) by announcing a single start time on the loudspeaker, so everybody follows one decision. Passing the flag decision along with a request is that loudspeaker.

i
Tip

Flagsmith can notify other systems through webhooks when flags change. Connect these to your chat tool or incident tracker so that everyone sees flag changes next to deployments. When something breaks, “what changed?” is the first question, and flag changes belong on that timeline.

The audit trail as a safety feature

Every step in the journey above leaves a trace. The audit log records who made the change, what the old and new values were, which environment it affected, and when it happened. This is more than paperwork. In an incident, it answers the most important question in the shortest time. In a review, it shows whether changes follow your process. In a regulated business, it can be the evidence an auditor asks for. Treat the log as a part of your system, not an afterthought, and learn where to find it before you need it.

KSetting Up the SDK the Right Way

Most flag-related incidents trace back to a small setting that nobody thought about. This chapter explains every important knob and what it is for.

The exact spelling of each setting varies by language, so use the official documentation for the names. The ideas, however, are universal. Here are the settings that matter most in a server-side SDK.

Required

Server-side environment key

The secret that identifies your environment and authorises the SDK. Load it from a secrets manager or a protected environment variable, never from source code.

Optional

API address

By default the SDK talks to Flagsmith Cloud’s edge service. If you self-host or run an Edge Proxy, you point this setting at your own address instead.

Mode

Local evaluation switch

Turns on in-memory evaluation. Remember it needs a server-side key, because it downloads the full environment document.

Mode

Refresh interval

How often, in seconds, the SDK downloads a new document in local mode. Shorter means fresher and busier; longer means calmer and staler.

Safety

Request timeout

The longest the SDK will wait for Flagsmith to answer. Keep it short compared with your own request budget so that a slow Flagsmith cannot make your users wait.

Safety

Retries

How many times the SDK tries again after a failure. A small number helps with brief glitches. A large number can pile extra waiting onto an already slow request.

Safety

Default flag handler

Your safety net. It receives the name of a flag that could not be fetched or found and returns a safe value, usually “off” for risky features.

Insight

Analytics

When enabled, the SDK reports how often each flag is evaluated so the dashboard can show usage. It is sent in batches in the background.

Network

Custom headers and proxy

Some company networks need extra headers, a corporate proxy, or custom certificates. The SDK usually lets you configure these explicitly.

Offline

Offline mode and handler

Tells the SDK to read the environment document from a source you supply, such as a local file, rather than calling Flagsmith.

Create the client once

The most important lifecycle rule is that the SDK client is built once, when the process starts, and shared for the life of the process. Think of it as a long-lived helper, not a throwaway tool. In local mode, creating the client downloads the whole environment document and starts a background refresher. If you create a new client for every request, you repeat that download for every request and leave a trail of background tasks behind you. That turns a clever optimisation into an outage.

1

Read the key securely

At startup, fetch the key from your secrets store. Fail loudly if it is missing; a service without a key should not pretend to be healthy.

2

Build one client

Create a single client with your chosen mode, timeouts, and default flag handler, and store it somewhere the whole application can reach.

3

Warm up before serving traffic

In local mode, wait for the first document to load before the service reports itself ready. Your load balancer’s health check should reflect this.

4

Serve requests

For each incoming request, fetch flags once, keep them in the request’s context, and use them wherever needed.

5

Shut down cleanly

When the process stops, close the client so its background tasks end and pending analytics are sent.

!
Warning

Choose your default flag handler carefully. For a risky new feature, the safe default is “off”. For a kill switch that protects a fragile dependency, the safe default might be “on” meaning “protection active”. The right fallback depends on what failure you fear most. Write the reasoning down next to the flag.

Processes, workers and runtimes

The phrase “one client per process” hides a detail that surprises many teams: how many processes does your service really run? Some web servers start several worker processes inside one container, and each worker is a separate process with its own memory. In that setup, each worker holds its own client, its own copy of the environment document, and its own refresher. If a container runs eight workers and you run fifty containers, you have four hundred clients, not fifty. Count them when you do your traffic and memory arithmetic, because refresh traffic scales with the number of clients.

Different runtimes also behave differently. A runtime built around a single event loop, such as Node.js, runs the refresher on a timer without blocking requests, but a very slow or hung download should still be protected by a timeout. A runtime with real threads, such as the Java virtual machine, typically runs the refresher in a small pool of background threads. A language that starts many short-lived processes may need an external shared cache or an Edge Proxy, because per-process downloads would repeat too often. Whatever your runtime, ask three questions: where does the client live, who refreshes it, and how does it stop?

i
Tip

When a service pauses its work during deployment or scaling events, confirm that the client is closed gracefully. A refresher that keeps running after the application thinks it has stopped can hold a container open, delaying rolling updates for no obvious reason.

LHigh Availability, Failure Scenarios and Recovery

A feature flag system must never become the reason your service goes down. Good design makes Flagsmith problems boring.

The guiding principle is called failing safe. If anything goes wrong in the flag layer, your service should continue to work with sensible default behaviour, not stop. The SDK supports this with timeouts, retries, a default flag handler, and, in local mode, the habit of keeping the last good document. The diagram below shows the order of fallbacks.

flowchart TD
  Q["Code asks for a flag"] --> M{"Local document in memory?"}
  M -- Yes --> L["Evaluate locally"]
  M -- No --> R{"Remote call succeeds within the timeout?"}
  R -- Yes --> OK["Use the answer from Flagsmith"]
  R -- No --> T{"Retries left?"}
  T -- Yes --> R
  T -- No --> DH{"Default flag handler defined?"}
  DH -- Yes --> DV["Use your safe default"]
  DH -- No --> ER["SDK raises an error"]
Figure 6 — The fallback chain: memory first, then network, then your safe default.
What goes wrongWhat the service experiencesHow to stay safe
Flagsmith unreachable while running (local mode)Refreshes fail; the last good document keeps serving answersAlert when the document is older than a few intervals
Flagsmith unreachable at startup (local mode)No document yet; behaviour depends on the SDK and your settingsRetry with backoff, bundle an offline document, and keep the service “not ready” until loaded
Flagsmith slow (remote mode)Every lookup waits, so user requests slow downShort timeout, default flag handler, and consider a circuit breaker
Key revoked or mistypedAuthentication errors; local refreshes stopRotate keys with overlap, monitor for repeated 401 or 403 responses
Flag deleted but code still asks for itMissing flag; SDK may raise an error without a handlerDefault flag handler and a clean-up process that removes code first, flags second
A bad flag change reaches productionNew behaviour appears for usersAudit log, quick revert, and approval steps for sensitive environments
Refresher stops silentlyRules slowly grow stale without any errorTrack document age as a metric and alert on it
Everyday analogy

A hospital has a main power supply, but it never depends on it alone. When mains power fails, a generator starts, and the lights barely flicker. Your flag layer should be designed the same way: the network is the mains supply, the in-memory document is the generator, and your default flag handler is the emergency torch in the nurse’s pocket.

Designing for the worst day

Plan an actual rehearsal. In a staging environment, block the network path to Flagsmith and watch what your service does. Does it still start? Does it still answer requests? Do logs make the problem obvious? Teams that rehearse find surprising gaps, such as a health check that insisted on a fresh document and therefore killed every healthy container during a short outage, which turned a minor issue into a total one.

Self-hosting for control

Teams that need strict control can run Flagsmith themselves, using containers behind a load balancer with a managed database. They then point the SDK at their own address. This removes dependence on the public internet, but moves the responsibility for availability, backups, and upgrades onto the team. Treat the self-hosted flag service as a tier-one dependency, with its own monitoring and runbook.

i
Remember

Local evaluation is a form of caching, and caches trade freshness for resilience. That trade is usually excellent, but it means a flag change made during an outage will not reach your service until contact is restored. Keep a second, independent way to stop a dangerous feature, such as a configuration deployment or a load balancer rule.

A small runbook for flag trouble

When something looks wrong, a short, calm checklist beats improvisation. The steps below work for most incidents involving the flag layer, and they are worth printing into your team’s runbook.

1

Check what changed

Open the audit log and look for flag changes in the last hour. If a recent change lines up with the symptoms, revert it first and investigate afterwards.

2

Check the document age

In local mode, look at how old each instance’s document is. Old documents point to a broken refresher, a revoked key, or a network problem.

3

Check the fallback rate

A rising count of default handler hits means the SDK is failing to get real answers. The system is safe but running on guesses, so treat it as urgent.

4

Use the second lever

If Flagsmith cannot be reached and a feature must stop now, use your independent method, such as a configuration change or a routing rule, then fix the flag path afterwards.

5

Write it down

Record what happened, how long it took to notice, and what would have caught it sooner. Turn each answer into a new alert, test, or habit.

MPerformance and Scalability

Flags sit on the hot path of your busiest code. Here is how to keep them from becoming a bottleneck as traffic grows.

Performance has two sides: latency (how long one lookup takes) and throughput (how many lookups you can handle per second). In remote mode, latency is dominated by the network. Even a well-placed service pays a small round trip, and a poorly placed one pays much more. In local mode, latency is tiny, because evaluating a handful of rules in memory is a small piece of computation. At that point your biggest costs are elsewhere, which is exactly where you want them.

ms
typical cost of one remote lookup, depending on distance
µs
typical cost of one local lookup from memory
O(instances)
how refresh traffic grows: with servers, not with users

Scaling the number of instances

When you add servers, each new instance performs its own initial download and its own refreshes. This is fine at normal scale, but at very large scale you may run thousands of instances. Two techniques help. First, spread out the refreshes. If every instance started at the same second and refreshes on the same schedule, they would hit Flagsmith in synchronised waves. Letting each instance start its timer from its own start-up moment naturally spreads the load. Second, put an Edge Proxy or your own cache between your fleet and Flagsmith, so thousands of instances share one upstream conversation.

Memory and the size of the document

The environment document grows with your configuration: more features, more segments, more overrides, and more rules all make it larger. A modest setup yields a small document, comfortably within memory. A very large setup, for example with hundreds of thousands of identity overrides, can be heavy to download and hold on every instance. If you reach that scale, reconsider whether identity overrides are the right tool. A segment with a rule is usually cheaper than a hundred thousand individual exceptions.

Serverless and short-lived runtimes

Functions that run on demand, such as AWS Lambda, behave differently from long-running servers. Their environment can be frozen between calls, which pauses background timers, so a refresher cannot be trusted to run on schedule. Start-up costs also matter, because a cold start that downloads a large document adds delay. For these runtimes, remote evaluation or an Edge Proxy nearby is usually the calmer choice, and offline mode with a bundled document can serve as a last-resort fallback.

i
Tip

Do not call the SDK inside tight loops. If you are processing 10,000 items in a batch, decide once for the batch (or once per identity group), keep the result in a local variable, and use it for every item. Even a microsecond lookup becomes a problem when repeated ten million times.

What helps performance

  • One shared client per process
  • Local evaluation for hot paths
  • One lookup per request, reused everywhere
  • An Edge Proxy for very large fleets
  • Small, focused sets of segments

What quietly hurts

  • Creating a client per request
  • Remote calls inside loops
  • Very short refresh intervals everywhere
  • Huge numbers of identity overrides
  • Long timeouts with many retries

A worked capacity example

Numbers make the trade-offs concrete, so let us work through one realistic example. A company runs 60 containers, each with 4 worker processes, so 240 clients in total. Each client refreshes every 30 seconds. That produces 240 downloads every 30 seconds, which is 8 downloads per second, or about 691,200 downloads per day. If the environment document is 500 kilobytes, each refresh moves about 500 kilobytes, and the fleet moves roughly 4 megabytes per second of flag data in total. That is perfectly manageable, but it is no longer a rounding error, and it shows why changing the interval from 30 to 5 seconds would multiply the load by six and deserves a careful decision.

Now compare this with the remote alternative. If the same fleet serves 20,000 requests per second and each request makes one flag lookup, remote evaluation would produce 20,000 calls per second, which is 1.7 billion calls per day. The local approach makes about 691,200 calls a day for the same fleet, which is around 2,500 times fewer calls. This single comparison explains why almost every large system ends up on local evaluation or an Edge Proxy.

i
Remember

Always measure your own document size. It depends on your flags, segments, and overrides, and it can change over time. Put its size on a dashboard so that slow growth is noticed long before it becomes a problem.

NSecurity: Protecting Keys, Data and Decisions

A flag platform can switch features on for the whole world. Treat access to it with the same care as access to your production servers.

Security in the server-side SDK has three layers: protecting the key, protecting the data you send, and protecting the decisions the flags control. Each layer has its own simple rules.

Layer one: the key

The server-side environment key is a secret in the same family as a database password. Anyone holding it can read the full rulebook for that environment, including every segment and override. Keep it out of source code, container images, build logs, chat messages, and browser-visible files. Store it in a proper secrets service, such as AWS Secrets Manager or a similar vault, and give only the services that need it permission to read it. Create separate keys for each environment and, where possible, for each major service, so that a leak can be traced and closed without breaking everything else.

Everyday analogy

A server-side key is like the master key to a block of flats, while the client-side ID is like the number on the front door. Everyone can see the door number, and that is fine. The master key must stay in a locked box, and a spare should be easy to cut and the old one easy to cancel if it ever goes missing.

Layer two: the data you send

When you pass an identity and traits, you may be sending information about real people to a third party, or at least to another system. Use opaque identifiers, such as an internal user number, rather than email addresses or names. Send only the traits that a segment actually needs. Do not send passwords, payment details, health information, or anything that would worry you if it appeared in a log. If your privacy rules demand it, choose self-hosting or a hosted region that satisfies them, and use transient identities and traits (where your SDK supports them) so that nothing is stored.

Layer three: the decisions

A flag is only as trustworthy as the process around it. Use dashboard roles so that only the right people can change production flags. Turn on the audit log and review it after incidents. For sensitive environments, use approval workflows, where a second person must approve a change before it takes effect, if your plan includes them. Connect single sign-on so that leaving employees lose access immediately.

Do

Rotate keys on a schedule

Create the new key, deploy it, confirm everything works, then delete the old one. Doing this regularly means the day you must do it in a hurry is not your first time.

Do

Use TLS everywhere

All SDK traffic should travel over encrypted connections. If you run a proxy or self-host, make sure internal hops are encrypted as well.

Do

Enforce rules on the server

If a flag unlocks a paid feature, check it in the backend where it cannot be bypassed, not only in the page that the user can alter.

Avoid

Logging the key

Debug logs that print configuration are a classic leak. Make sure the key is masked wherever settings are displayed.

Avoid

Personal data in traits

Traits are meant for targeting facts, not for storing profiles. Keep them short, coarse, and non-sensitive.

Avoid

Flags as the only lock

A flag controls availability; it does not replace authentication or permission checks. Use both together.

!
Warning

Never confuse “hidden” with “secure”. If a feature is only hidden by a flag but the underlying endpoint accepts requests from anyone, a curious person can still call it directly. Always make sure the endpoint itself checks both the flag and the user’s rights.

A short security review checklist

1

Where are the keys stored?

Confirm every key lives in a secrets service, with access limited to the services that use it, and that no key appears in code, images, or logs.

2

Who can change production?

List the people and roles allowed to edit flags in the production environment. Remove anyone who no longer needs access.

3

What do we send as traits?

Read the list of traits and identities your services send. Remove anything personal that no segment actually uses.

4

How fast can we rotate a key?

Practise rotating one server-side key end to end. If it takes longer than an hour, simplify the process.

5

Do endpoints check rights?

Confirm that hidden features are also protected by normal authentication and permission checks.

OMonitoring, Logging and Metrics

You cannot trust what you cannot see. A few well-chosen signals turn the flag layer from a black box into something you can reason about at three in the morning.

Start with the question every on-call engineer asks: “what changed?” Flag changes are changes to production behaviour, just like deployments. Make them visible. Flagsmith keeps an audit log, can send webhooks, and connects to tools such as Datadog and other observability or analytics platforms, so that a flag change can appear as a marker on your graphs. When a latency chart jumps, you want to see in one glance that a flag was changed two minutes earlier.

SignalWhy it mattersExample alert idea
Document age (local mode)Shows whether the refresher is alive and the rules are freshAlert when older than three refresh intervals
Refresh success rateReveals network, key, or API problems earlyAlert on repeated failures over several minutes
Lookup latency (remote mode)Shows how much time flags add to user requestsAlert when the slow tail grows beyond your budget
Default handler hit rateCounts how often you ran on fallback valuesAlert when it rises above a low baseline
Authentication errorsPoints to a revoked, expired, or wrong keyAlert on any sustained burst
Flag usage countsFinds flags that nobody reads any moreWeekly review list of flags with zero evaluations
Flag change eventsLinks behaviour changes to people and timesShow as markers on service dashboards

What to log, and what to leave out

Log decisions in a way that helps debugging without leaking secrets. A good log line says which flag was checked, which value came back, and which request or correlation ID it belongs to. Do not log the key. Be careful with traits, because they may contain personal facts. For a rarely seen problem, such as “why did this one customer get the old page?”, it is far easier to find the answer if your logs record the flag name, the value, and the identity label for that request.

i
Tip

Attach the flag values used by a request to your tracing system as small tags on the trace. When a customer reports strange behaviour, you can look up their trace and see exactly which flags shaped it. This single habit can shorten investigations dramatically.

A realistic investigation

Error rates on a checkout service rise at 14:05. The engineer opens the dashboard, sees a marker at 14:03 showing that a new payment routing flag was ramped from 10 to 50 percent, and sees on the trace tags that failing requests all carry the new flag value. The ramp is set back to 10 percent, then to zero. Time to find the cause: a few minutes, because the flag layer was observable.

Setting service level goals for the flag layer

Once you can see the signals, decide what “healthy” means. A service level objective is a promise you make to yourself, such as “ninety-nine point nine percent of flag lookups complete within five milliseconds” or “no instance runs for more than five minutes with a document older than three minutes”. Goals like these turn vague feelings into clear tests. They also settle arguments: if the goal is met, the flag layer is not the cause of your problem, and you can look elsewhere.

Keep the goals modest and honest. In local mode, lookups should be almost free, so the interesting goals are about freshness and fallback rates. In remote mode, the interesting goals are about latency and error rates. Review the goals after each incident, and tighten them only when the business really needs it, because every extra nine of reliability costs time and money.

PDesign Patterns and Anti-patterns

The same few flag shapes appear again and again in healthy systems. The same few mistakes appear in unhealthy ones.

Patterns worth using

Pattern

Kill switch

A flag whose only job is to turn a risky or expensive feature off fast. It stays in the code for as long as the feature exists, and its default is chosen for safety.

Pattern

Gradual rollout

Release to 1, 5, 25, 50, then 100 percent while watching error rates and latency at each step. Stable percentages keep the same users in at every stage.

Pattern

Dark launch

Run new code in production for real traffic, but hide its results from users. It tests performance and correctness before anyone depends on it.

Pattern

Ring deployment

Use segments to release first to staff, then to friendly customers, then to everyone. Each ring is a chance to catch a problem while the audience is small.

Pattern

Entitlement gating

Use plan or tenant traits in segments to unlock features by subscription, so sales and product teams can change packages without engineering work.

Pattern

Operational tuning

Use remote config values for numbers you want to adjust live, such as batch sizes, timeouts, or cache durations, to calm a struggling system during an incident.

Pattern

Experiment with variants

Use multivariate values to compare two or three versions of a behaviour and measure which wins, with each identity seeing the same version every time.

Pattern

Decide at the edge

Evaluate flags once at the entry point of a request, keep the decision in a small object, and pass it down. Deep code then asks the object, not the SDK.

Patterns to avoid

ANTI-PATTERN 01Avoid
What it is

Creating a new SDK client for every request, job, or function call.

Why it hurts

In local mode each new client downloads the whole environment document and starts a background refresher. Under load this multiplies traffic to Flagsmith, wastes memory, and leaves background tasks piling up. In remote mode it throws away connection reuse.

Do this instead

Create one client at process start and share it for the life of the process.

ANTI-PATTERN 02Avoid
What it is

Flags that depend on other flags, with code like “if flag A and not flag B, unless flag C”.

Why it hurts

The number of possible combinations grows quickly: ten independent flags allow 1,024 combinations, and nobody has tested most of them. Bugs appear only in strange combinations that are hard to reproduce.

Do this instead

Keep flags independent, keep the number of live flags small, and retire flags soon after they have done their job.

ANTI-PATTERN 03Avoid
What it is

Leaving release flags in the code forever after the rollout is finished.

Why it hurts

Dead branches confuse new engineers, bloat tests, and hide risk. A flag nobody remembers can be flipped by accident and wake up code that has not run for a year.

Do this instead

Give every release flag an owner and an expected removal date. Remove the flag and the old code path together, as part of the same piece of work.

ANTI-PATTERN 04Avoid
What it is

Reusing an old flag name for a new purpose.

Why it hurts

Old code that still reads the flag can wake up and behave in ways nobody expects. This mistake has caused real, expensive disasters, as the next chapters show.

Do this instead

Retire old names for good and give every new purpose a fresh, clearly descriptive name.

ANTI-PATTERN 05Avoid
What it is

Using flags as a permanent substitute for configuration management or access control.

Why it hurts

Flags are designed to be temporary switches and safe tuning values. Using them as the only barrier for permissions, or as a dumping ground for hundreds of settings, makes the system hard to audit and fragile.

Do this instead

Keep real permissions in your authorisation system and stable settings in your configuration system. Use flags for change and experimentation.

Putting patterns together: a launch plan

Real launches combine several patterns. Imagine a new search ranking engine. First, the team deploys it dark, with a kill switch set to off, and runs it in the background against real traffic to compare results without showing them (dark launch). Next, a segment for internal staff turns it on, so employees use it daily (ring deployment). Then a gradual rollout takes it from 1 to 5 to 25 percent of customers, while the team watches latency and click rates. A remote config value controls how many results are re-ranked, so the team can turn the cost down during a traffic spike (operational tuning). At 100 percent, the team waits a full month, then removes the flag, the old ranking path, and the tuning value together. Each step is small, visible, and reversible, which is the whole point.

QBest Practices and Common Mistakes

Good habits around flags matter more than clever configuration. These are the practices that experienced teams settle on.

The life of a healthy flag

1

Create with a clear name and owner

Use a name that says what it controls, not who asked for it. Add tags for team and purpose, and note when it should be removed.

2

Ship the code dark

Deploy with the flag off. Confirm the deployment is healthy before anyone sees the new behaviour.

3

Test in lower environments

Switch the flag on in development and staging first. Test both the on and off paths, because both must work.

4

Ramp up slowly in production

Start with staff, then a small percentage, then more. Watch your metrics at each step and pause when anything looks odd.

5

Reach one hundred percent and wait

Leave it fully on for a safe period, long enough to cover your slowest business cycle, such as a month-end process.

6

Remove the flag and the old code

Delete the old path in code first, deploy, then delete the flag in the dashboard. Never the other way round.

Habits that pay off

  • Fetch flags once per request and pass them along
  • Always define a thoughtful default flag handler
  • Name flags by purpose and group them with tags
  • Keep separate keys and flags per environment
  • Review flag usage and clean up every sprint
  • Rehearse a Flagsmith outage in staging

Mistakes that hurt

  • Using the wrong key type in the wrong place
  • Assuming a dashboard change is instant in local mode
  • Passing no identity, then wondering why percentages fail
  • Forgetting traits, so segments never match
  • Deleting a flag while code still reads it
  • Letting the flag count grow without limit
i
Testing note

Both sides of a flag deserve tests. A common trap is to test only the new path and discover in production that the “off” path was broken by the same change. In automated tests, use offline mode or a fake client with fixed values so tests never depend on the network or on live dashboard settings.

!
Common confusion

“My segment is not matching” is almost always one of four things: the identity was not supplied, the trait name has a different spelling or capital letters in code and in the dashboard, the trait has the wrong type (the text “5” versus the number 5), or the SDK is in local mode and the traits were never passed in. Check these four before anything else.

Naming conventions that age well

Names are the user interface of your flags. A good name says what it controls and, when helpful, what kind of flag it is. For example, a release flag for a new checkout might be called “release_new_checkout”, an operational switch for a fragile partner might be “kill_partner_shipping_lookup”, and a plan-based feature might be “entitlement_advanced_reports”. The prefix tells the next engineer how long the flag is expected to live: release flags are short, kill switches are long, and entitlements are as long as the pricing plan. Avoid names that mention a person, a ticket number alone, or a date, because those lose meaning quickly.

A short code review checklist for flag changes

When a pull request adds or changes a flag, ask five quick questions. Is the flag name clear and unique? Is the safe default chosen on purpose? Are both the on path and the off path tested? Is the flag read once per request, instead of scattered through deep code? Is there an owner and a planned removal date? A review that takes two minutes and asks these five questions prevents most of the mistakes described in this guide.

RAdopting the SDK: A Practical Roadmap

Knowing the theory is one thing. Here is a calm, step-by-step plan for bringing the server-side SDK into a real organisation without drama.

The biggest risk in adopting feature flags is not technical. It is trying to do everything at once. Teams that introduce the SDK across fifty services in a single month often end up with inconsistent naming, forgotten keys, and nobody who owns the cleanup. A staged approach avoids this and builds confidence along the way.

1

Pick one service and one flag

Choose a low-risk service and a single feature that is easy to understand. The goal of this stage is learning, not impact. Use remote evaluation to keep the setup trivial.

2

Agree the house rules

Write a one-page guide covering flag naming, tags, ownership, default handler policy, and how long release flags may live. Short and clear beats long and ignored.

3

Set up secrets and environments

Create separate environments, create separate server-side keys for each, and store them in your secrets manager with narrow access. Test key rotation once while the stakes are low.

4

Add observability

Before expanding, connect logs, metrics, and flag change notifications. A system you cannot see is not ready for more users.

5

Move busy services to local evaluation

For services with heavy traffic, switch to local evaluation, add the readiness check for the first document, and measure the change in latency and request counts.

6

Rehearse failure

Block Flagsmith in staging and confirm that services start, serve, and recover. Fix the gaps you find. Repeat this exercise when you change the setup.

7

Make cleanup routine

Put a short flag review into your regular planning rhythm. List flags that are fully on or fully off for a long time, and assign someone to remove each one.

Who owns what?

A successful rollout clarifies roles early. Engineers own the code that reads flags and the removal of old flags. Product managers often own the decisions about who sees a feature and when, using segments and percentages in the dashboard. Site reliability and platform teams own keys, secrets, monitoring, and the runbooks for failure. Security and compliance teams review what traits are sent and who may change production settings. When everybody knows their part, flag changes become a calm routine instead of a source of arguments.

Everyday analogy

Introducing flags is like introducing traffic lights into a town that only had stop signs. The lights are useful only if drivers know the rules, the signals are maintained, and someone fixes them when they break. A town that installs lights everywhere in a week, with no maintenance plan, gets more confusion, not less. Install them one junction at a time.

Measuring whether it is working

Decide up front how you will know the effort is paying off. Good measures include the time it takes to turn off a faulty feature (it should fall from many minutes to under one or two), the number of emergency rollbacks that required a deployment (it should fall toward zero), the share of releases that went out dark first (it should rise), and the number of flags older than a set age (it should stay low). Review these every few months, and share the results with the wider team so the habit sticks.

Minutes to seconds
typical goal for turning off a faulty feature
Fewer
emergency redeployments for rollback
Low
count of flags past their planned removal date
i
Remember

The SDK is a means, not a goal. The goal is calmer releases, faster recovery, and the confidence to ship small changes often. If your flag count and your anxiety are both growing, slow down and tidy up before adding more.

SReal-World and Industry Examples

Feature flags are not a fashion. Some of the best-known engineering organisations built whole ways of working around them, and one famous disaster shows what happens when flags are handled carelessly.

Facebook: gatekeeping and dark launches

Facebook has described an internal system called Gatekeeper that decides which users see which changes, which lets engineers release to a small slice of people first. Before launching Facebook Chat in 2008, the company also used a “dark launch”: the chat system ran against real production load while remaining invisible to users, so engineers could see whether it would hold up. The lesson for the server-side SDK is that flags let you test capacity as well as correctness.

Etsy: deploying many times a day

Etsy became a well-known example of continuous deployment, pushing changes to production dozens of times each day. Configuration flags let unfinished work sit safely in production, switched off, until it was ready. This removed the fear that comes with large, infrequent releases, because every individual change was small and reversible.

Netflix and Google: careful rollouts with automated checks

Netflix and Google jointly open-sourced a tool called Kayenta for automated canary analysis, which compares a small new rollout against the old version and judges whether the new one is healthy. Feature flags and percentage rollouts are natural partners for this idea: you route a small, stable group to the new behaviour, measure, and then widen or retreat based on evidence.

Uber: dynamic configuration at scale

Uber’s engineering teams have written publicly about an internal dynamic configuration system, known as Flipr, which lets services change behaviour without redeploying. The same need, fast and safe changes across a very large fleet of services, is the one that a server-side SDK with local evaluation meets for everyone else.

Knight Capital: the cautionary tale

In August 2012, the trading firm Knight Capital lost about 440 million US dollars in roughly 45 minutes. Investigations reported that an old flag, which had once controlled long-retired code, was reused for a new feature. One of eight servers did not receive the new software, so on that server the reused flag woke up the old code instead. The old code started sending unwanted orders at high speed. Three lessons stand out: never reuse flag names, remove dead code and old flags, and make sure every server runs the same version before a flag is switched on.

An illustrative setup on AWS

To bring everything together, here is a typical, illustrative arrangement for a busy API running on Amazon Web Services. It is an example of how the pieces fit, not a required recipe. Requests enter through Amazon API Gateway, pass an Application Load Balancer, and reach containers running on Amazon ECS. Each container holds one shared SDK client in local evaluation mode. The server-side key is stored in AWS Secrets Manager and given only to the task role of that service. Metrics and logs flow to Amazon CloudWatch, including document age and the default handler hit rate. The containers talk to Flagsmith Cloud, or to a self-hosted Flagsmith or Edge Proxy inside the same network.

flowchart LR
  U["End Users"] --> APIGW["Amazon API Gateway"]
  APIGW --> ALB["Application Load Balancer"]
  ALB --> T1["ECS Task 1 with SDK"]
  ALB --> T2["ECS Task 2 with SDK"]
  SM["AWS Secrets Manager"] --> T1
  SM --> T2
  T1 --> FS["Flagsmith Edge API or self-hosted Flagsmith"]
  T2 --> FS
  T1 --> CW["Amazon CloudWatch logs and metrics"]
  T2 --> CW
Figure 7 — An illustrative AWS layout: secrets, SDK clients, flag service and monitoring.
i
Tip

In this layout, scaling out from 4 to 400 tasks multiplies refresh traffic by 100, but not user traffic. Plan your upstream capacity around task count, and consider placing an Edge Proxy in front when task counts reach the thousands.

TFrequently Asked Questions

Short answers to the questions people ask most often when they start using the server-side SDK.

Q1Can I use the server-side SDK inside a web page or a mobile app?
No. The server-side SDK needs a secret key, and anything shipped to a browser or a phone can be read by the user. Use a client-side SDK with the public environment ID for those places, and keep the server-side SDK for code that you control.
Q2Which mode should I start with?
If you are just learning or your traffic is low, remote evaluation is the simplest. For services with steady or heavy traffic, move to local evaluation once you are comfortable, because it is faster, cheaper, and more resilient.
Q3How quickly does a dashboard change reach my service?
In remote mode, on the very next lookup. In local mode, within about one refresh interval, which is usually around a minute at the default, plus a little caching time.
Q4What happens if I ask for a flag that does not exist?
Without a default flag handler, many SDKs raise an error. With a handler, you decide what comes back. Defining a handler is strongly recommended so a typo or a deleted flag does not turn into an outage.
Q5Are traits saved when I use local evaluation?
No. In local mode the traits you pass are used for that decision only. If a segment depends on a trait, you must supply the trait on each evaluation. In remote mode, traits are normally stored with the identity unless you mark them as transient.
Q6Does my service need Flagsmith to be online for every request in local mode?
No. Once the first document has been downloaded, requests are answered from memory. Flagsmith only needs to be reachable for the first download and for later refreshes, and a short outage simply means your rules stay a little out of date.
Q7Can I run Flagsmith myself?
Yes. Flagsmith is open source and can be self-hosted, for example with containers on your own infrastructure. You then point the SDK at your own address. You become responsible for its availability, backups, security, and upgrades.
Q8How should I test code that depends on flags?
Do not call the live service in automated tests. Use offline mode or a fake client with fixed values, and test both the “on” and “off” paths. Add a small number of integration tests against a dedicated test environment.
Q9Is it safe to share one client across many threads or requests?
That is exactly how the client is meant to be used: one instance per process, shared by everything. Details about thread safety vary by language, so confirm them in the official documentation for yours.
Q10Can I run A/B tests with it?
Yes. Multivariate options split identities by percentage in a stable way. To judge which version wins, send the chosen variant to your analytics tool and compare outcomes there, since Flagsmith decides who sees what while your analytics tool measures the results.
Q11How many flags are too many?
There is no magic number, but the real limit is human understanding. If nobody can explain what each flag does and who owns it, you have too many. Prune regularly, and treat a growing list of old flags as a warning sign.
Q12Will local evaluation reduce my hosted bill?
Often, yes, because lookups no longer count as individual requests to the service; only the periodic document downloads do. Check how your plan counts requests, since pricing details can change.

USummary and Key Takeaways

The whole story in one place: what to remember when you close this page and open your editor.

The Flagsmith server-side SDK is the bridge between a switch in a dashboard and a behaviour in your running backend. It earns its place by separating deployment from release, so you can ship code safely, release it slowly, and retreat in seconds. Everything else in this guide is detail about doing that well: choosing a mode, configuring the client, failing safely, guarding the key, and keeping the list of flags tidy.

Key Takeaways

  • Server-side means secret. The server-side environment key unlocks the full rulebook, so keep it in a secrets manager and never in a browser, app, or repository.
  • Pick the right mode. Remote evaluation is simple and always fresh but pays a network trip per lookup. Local evaluation answers from memory in microseconds and refreshes on a timer, which is why high-traffic services prefer it.
  • Decisions follow a fixed order. Identity override first, then segment, then variant or environment default, with stable hashing keeping each identity on the same side of a percentage split.
  • Create one client and share it. Build it once at startup, wait for the first document in local mode, fetch flags once per request, and close the client at shutdown.
  • Always fail safe. Use short timeouts, a thoughtful default flag handler, and the last good document so that a Flagsmith problem never becomes your outage.
  • Make flags visible. Track document age, refresh failures, fallback rates, and flag change events, and put flag changes on the same timeline as deployments.
  • Keep flags short-lived and tidy. Name them clearly, give them owners, remove them with their old code, and never reuse a retired name.