Environment Keys in Flagsmith: Client-Side and Server-Side

Environment Keys in Flagsmith: Client-Side and Server-Side

A complete guide to the two keys that connect every application to Flagsmith: what each one is, what it can and cannot do, where it may live, how to store, rotate, and protect it, and how to respond when something goes wrong.

A developer is putting the finishing touches on a new web page. The page needs a feature flag, so she opens the Flagsmith dashboard, finds a long string labelled as a key for the production environment, and pastes it into her front-end configuration. The page works. The flag toggles. She commits the change, and the deployment goes out before lunch. Nothing looks wrong. But which string did she copy? One of the two possible answers is perfectly harmless. The other quietly hands every visitor to the website a complete map of the company’s targeting rules.

Flagsmith gives every environment two different kinds of key, and they look deceptively similar: both are long, random-looking strings. They are used in the same place, a setting when you start the SDK. Yet they sit at opposite ends of the security spectrum. One is designed to be printed on a billboard. The other must be guarded like a bank vault combination. Confusing them is one of the most common and most avoidable mistakes in feature flag work.

This guide explains both keys from first principles. You will learn what each one is for, how Flagsmith treats a request that carries each one, which SDKs use which, how to store them, how to rotate them without downtime, how to detect and respond to a leak, and how to build habits that keep you out of trouble. No code is needed, and every technical word is explained the first time it appears.

AWhy Environment Keys Exist

Before comparing the two keys, we need to understand the two jobs a key performs: saying who is asking, and deciding what they may do.

Every request needs an address

Flagsmith serves flags for many customers, many projects, and many environments at the same time. When an SDK sends a request, Flagsmith must instantly know which environment’s flags are wanted. A production environment and a development environment may share a project, and even share feature names, but they hold different values. The key attached to each request is how Flagsmith finds the right one. In this sense, a key works like an address: it points at one specific environment and no other.

Every request also needs permission

An address alone is not enough. If knowing an environment’s address were all it took to read everything inside it, then anyone who learned the address could read everything. So Flagsmith attaches a second meaning to the key: a level of trust. Different keys are allowed to do different things. A key that is meant to be public may only perform a narrow set of low-risk actions. A key that is meant to be secret may perform broader actions, such as downloading the complete rulebook for the environment. The same idea exists in many systems: some identifiers are safe to show, and others are secrets.

Everyday analogy

Think of an apartment building. The street number painted on the front is an address: everybody knows it, and knowing it lets you ring the bell and ask a question at the door. The master key kept in a locked box in the manager’s office is a credential: it opens every flat. Flagsmith’s client-side ID is the street number. Flagsmith’s server-side key is the master key. Mixing them up means either hiding your street number for no reason, or painting your master key on the front door.

Why two keys, not one?

Modern applications run in two very different places. Some code runs on servers you control, where nobody outside your team can look inside. Other code runs on devices you do not control, such as web browsers and phones, where any user can inspect everything. A single key could not serve both safely. If it were secret, front-end code could never use it. If it were public, back-end code would be given too little power or the public would be given too much. Two keys solve this cleanly: a public one with limited abilities, and a secret one with greater abilities.

2
kinds of key per environment: public ID and secret key
1
environment each key points at, and no other
Many
server-side keys may exist for the same environment
i
Good to know

Names in the dashboard and the documentation have changed over the years. You may see older material that calls the public identifier an “environment API key” or similar. Always check which key is public and which is secret by reading the label next to it in the dashboard and in the current documentation, not by trusting the name you remember.

Three words that are often confused

Security conversations use three similar-sounding words, and keeping them apart makes keys easier to understand. Identification means saying who or what you are, such as giving a name. Authentication means proving it, such as showing a passport that others can check. Authorisation means the system deciding what you may do once it knows who you are. Environment keys touch all three, but not equally.

The client-side ID is mostly about identification: it says “I am asking about this environment”. It proves very little, since anyone can copy it, so it is a weak form of authentication, and that is why its powers are kept small. The server-side key adds real authentication: only someone who holds the secret can present it, so Flagsmith can trust that the caller is one of your own services. That trust is then turned into authorisation: a short list of things such a caller may do, including downloading the rulebook. The design principle is that the more a credential can do, the harder it must be to obtain, and the more carefully it must be kept.

i
Remember

A public identifier is a label, not a lock. Never design a system in which knowing a label is enough to do something dangerous. Flagsmith follows this rule: the label (client-side ID) can only do small, safe things, and anything larger needs the secret.

BThe Two Keys at a Glance

Here is the whole topic in one table. The rest of this guide expands every row.

QuestionClient-side environment IDServer-side environment key
Is it secret?No. It is designed to be visibleYes. Treat it like a password
Where may it live?Browsers, mobile apps, any client codeBackend services, workers, jobs, protected pipelines
Which SDKs normally use it?Client-side SDKs: JavaScript, React, mobile, and similarServer-side SDKs: Python, Node.js, Java, .NET, Go, Ruby, PHP, and similar
What can it read?Flags and values for one identity at a timeThe same, plus the complete environment document for local evaluation
What can it change?Possibly an identity’s traits, depending on settingsNot flag definitions; it cannot edit features or segments
How many per environment?One identifierOne or more, each named and revocable
If it leaks?Little harm in itself, though some data is exposed by designSerious: the whole targeting rulebook can be downloaded
How do you replace it?Rarely needed; it identifies, not authenticatesCreate a new key, deploy it, delete the old one
One is an address you can shout. The other is a key you must hide.

The easy memory trick

Ask a single question: “could a stranger see this string?” If the code is running in a place a stranger can open, such as a web page, a phone app, or a downloadable program, then the answer is yes, and only the client-side ID belongs there. If the code runs inside a server you control, and the string is loaded from protected storage, the server-side key is both allowed and appropriate. When in doubt, the safer choice is always the one with fewer powers.

!
Warning

The dangerous mistake is one-directional. Using the client-side ID on a server is merely a missed opportunity, since you lose local evaluation. Using the server-side key in a client is a leak. If you ever have to guess, guess the public one.

Myths and facts

Common beliefThe reality
“All environment keys are secrets”Only the server-side key is. The client-side ID is public by design
“The client-side ID is useless to attackers, so exposure is irrelevant”It is low risk, but the values it can read and the traits it may send are still worth designing carefully
“A leaked server-side key lets attackers switch my flags”It lets them read your rules and values; changing flags needs a separate management credential
“One key per project is enough”Keys are per environment, and one key per consumer is safer
“Deleting the key from the repository fixes the leak”The key remains in history; it must be replaced
“A private repository is a safe place for a secret”Private repositories can be reached with stolen logins, copied to laptops, and forked; use a secrets manager
“Using the server-side key everywhere is simpler and therefore fine”Simpler for you, and dangerous in any code a user can inspect

CWhere Keys Live in Flagsmith’s Structure

Keys belong to environments, and environments belong to projects. Understanding this hierarchy prevents a whole family of mix-ups.

Flagsmith organises everything in layers. At the top is your organisation, usually your company. Inside it live projects, typically one per product or application. Inside each project live environments, such as development, staging, and production. Inside each environment live your features, with their states, values, segments, and overrides. Keys sit at the environment layer. This is deliberate: it means the environment, and not the project or the organisation, is the unit of access.

Layer 1

Organisation

Your company account. Users, roles, and billing live here. It has no environment keys of its own, but it can hold separate administrative credentials.

Layer 2

Project

One application or product. It holds the list of features and segments that all its environments share as definitions.

Layer 3

Environment

One stage of life, such as production. It owns its own flag values and its own keys. This is where SDKs connect.

Layer 4

Feature

A named flag or value. Its state differs in each environment, which is why keys must be per environment.

What “one environment per key” means in practice

A key for production gives access to production flags only. A key for staging gives access to staging flags only. Even if the two environments contain a feature with the same name, a production key can never read the staging value, and a staging key can never read the production value. This isolation is the reason you can safely let a developer experiment freely in a development environment: the experiment cannot reach production, because the development keys do not point there.

flowchart TD
  Org["Organisation"] --> P1["Project: Shop Web App"]
  Org --> P2["Project: Mobile Backend"]
  P1 --> E1["Environment: Development"]
  P1 --> E2["Environment: Staging"]
  P1 --> E3["Environment: Production"]
  E3 --> K1["Client-side environment ID"]
  E3 --> K2["Server-side key: checkout service"]
  E3 --> K3["Server-side key: reporting job"]
  E1 --> K4["Its own client-side ID and server-side keys"]
Figure 1 — Keys hang off environments. Each environment has its own client-side ID and its own server-side keys.
Everyday analogy

Picture a hotel group with several hotels, each with several floors. A master key for the fourth floor of one hotel opens only those rooms and nothing else in the group. The group does not give out one key that opens every door in every hotel, because one lost key would then be a disaster. Environment keys follow the same discipline: small territory, small damage.

i
Remember

Because keys belong to environments, the same mistake can happen quietly in a different shape: a staging service accidentally configured with a production key. It will run, and it will read real production flags. Check which environment a key points at before you deploy, not after.

Counting keys: how sprawl happens

Key counts grow faster than most teams expect, because they multiply across layers. An organisation with 6 projects, 3 environments each, and 4 server-side keys per environment already has 72 server-side keys, plus 18 client-side IDs. Add temporary environments for pull requests, a handful of experimental sandboxes, and keys for the Edge Proxy, and the total can pass a few hundred within a year. Nobody planned this; it simply accumulates, one reasonable decision at a time.

Sprawl is dangerous because forgotten keys are unmonitored keys. A key that nobody remembers is a key nobody rotates, nobody revokes when a team is disbanded, and nobody would notice being used by a stranger. The remedy is cheap: record every key in an inventory with an owner, review the inventory each quarter, and delete anything without a living owner or a known purpose. Deleting an unused key is a small, safe action, and a short list is far easier to defend than a long one.

72
server-side keys from 6 projects, 3 environments, 4 keys each
18
client-side IDs for the same layout, one per environment
Quarterly
a sensible rhythm for reviewing the key inventory

DThe Client-Side Environment ID in Depth

It is long, random, and public on purpose. Here is exactly what the client-side ID is, and why exposing it is acceptable.

What it is

The client-side environment ID is a public identifier for one environment. Think of it as the environment’s name tag. When a browser or mobile app starts the Flagsmith SDK, it supplies this ID. Flagsmith reads it and knows which environment’s flags to prepare. The ID is placed into the front-end code, which means that anyone who opens the page’s developer tools, or unpacks the app, can read it. The design assumes this will happen.

What it can do

With only the client-side ID, a caller can ask for the flags that apply to one identity, along with those flags’ on/off state and values. This is what a front end needs: “show me what this particular user should see.” Depending on how the environment is configured, a caller can also send traits for that identity, so that segments can target by them. Those two abilities are all the front end requires.

What it cannot do

Cannot

Download the rulebook

The complete environment document, with every segment rule and override, requires the secret key. The public ID is refused.

Cannot

Edit flags

It cannot create, change, or delete features, segments, or environments. Management is a separate credential entirely.

Cannot

Run local evaluation

Local evaluation needs the full document, so it needs the server-side key. Client SDKs always rely on the server to decide.

Cannot

Reach other environments

It points at one environment only. Staging and development remain out of reach.

Why public is acceptable

Three ideas make exposure tolerable. First, the ID only identifies; it does not unlock management or bulk data. Second, the answers a client can obtain are limited to what a front end legitimately needs: the flags for the identity being asked about. Third, any feature a user can see in the interface will necessarily be visible to that user anyway, because the interface must behave differently. Hiding the flag state from the person whose screen it controls is neither possible nor useful.

!
Important nuance

“Safe to expose” does not mean “free of consequences”. Because anyone can use the public ID, anyone can ask what flags apply to any identity label they invent, and anyone may be able to send traits. A later chapter on exposure risks explains what that means for your design. The short version: never put secrets inside flag values that a client can read.

Where you will see it

A single-page web application initialises the Flagsmith SDK with the client-side ID in its JavaScript bundle. A mobile app does the same in its configuration. A marketing site loads it into a small script. In each case the ID travels to the user’s device, and that is fine, as long as nothing secret travels with it.

How a client SDK uses the ID over time

Following the ID through the life of a client application shows how it behaves in practice. When the application starts, the SDK is given the ID and, usually, an identity for the current user. It sends a request carrying the ID and asks for that identity’s flags. Flagsmith recognises the ID, finds the environment, evaluates the rules for that identity on its side, and returns the results. The SDK stores them in memory, and sometimes on the device, so the interface can read them instantly without waiting for the network again.

During the session, the application may update the identity’s traits, for example after the user changes their plan, and ask again. Each request repeats the same ID. Some client SDKs also support receiving updates when flags change, so the interface can react without a reload; others simply refresh on demand or at intervals. In every case, the ID is a constant companion that tells Flagsmith which environment the questions are about, while the user’s identity, which changes, tells it who they are about.

Start

Initialise

The SDK receives the ID and the user’s identity and requests the first set of flags.

Use

Read from memory

The interface reads flag values from the SDK’s stored results, quickly and without further requests.

Update

Refresh on change

When traits change or the app returns to the foreground, the SDK asks again using the same ID.

End

Session closes

The stored results disappear with the page or are cached on the device, depending on the SDK and settings.

EThe Server-Side Environment Key in Depth

It looks like the public ID, but it is a different thing altogether: a secret that unlocks more power and demands more care.

What it is

The server-side environment key is a secret credential for one environment. You create it in the dashboard, in the environment’s SDK keys area, and you can create several, each with a name of your choice. The dashboard shows the full value at creation, and you should copy it straight into a secrets manager. Server-side keys typically carry a recognisable prefix, which helps both humans and automated scanners spot them. Check the current documentation for the exact prefix in use.

What it unlocks

Can

Evaluate flags remotely

Ask Flagsmith for the flags that apply to an identity, exactly as a client could, with the trust level of a backend.

Can

Download the environment document

Fetch the entire rulebook for the environment, which enables local evaluation inside your own process.

Can

Send usage analytics

Report how often flags are evaluated, so the dashboard can show which flags are alive.

Cannot

Manage flags

It cannot edit feature definitions, segments, or environments. Those need a human login or an administrative token.

Why it is the sensitive one

Remember what the environment document contains: every feature, every segment with its rules, every percentage split, and, where supported, every identity override. With the server-side key, a single request returns all of it. An outsider holding the key could learn which customers are beta testers, how pricing tiers are targeted, which unreleased features are waiting, and how experiments are split. The key does not let them change anything, but knowledge of your targeting logic is itself valuable, and a leaked key is a stubborn problem because it keeps working until someone deletes it.

Everyday analogy

Imagine a restaurant’s recipe book, with every secret ingredient and every supplier price. A customer who is shown one dish, which is the client-side experience, learns nothing about the book. A person who photographs the whole book, which is what the server-side key allows, learns everything. They cannot cook in the restaurant’s kitchen, since they cannot change the real recipe book, but a competitor would very much like that photograph.

Many keys, many names

You are not limited to one server-side key per environment, and that is a feature. Create one per service, or one per team, and give each a descriptive name such as “checkout-service-prod”. Separate keys let you trace which service uses which key, revoke a single key without disturbing the others, and rotate keys one service at a time. A single shared key for the whole company is convenient on day one and painful on the day it leaks.

i
Tip

Name keys after the consumer and the environment, not after the person who created them. People leave and change roles; services and environments endure. A name that says “reporting-job-staging” is useful for years, while one that says “dave-test” is a mystery within a month.

The life of a key from birth to deletion

Every server-side key passes through a lifecycle, and managing it deliberately at each stage is the heart of good key hygiene. It is born when someone creates it in the dashboard, and the full value is shown. It is placed in a secrets manager and linked to the consumer that will use it. It is used every time the service starts, and, in local evaluation, every time the poller refreshes. It is watched by metrics that show authentication failures and by scanners that look for stray copies. It is rotated on a schedule or after an event. Finally it is retired: deleted from Flagsmith and removed from the secrets manager.

The stages most often forgotten are the last two. Teams create and use keys diligently and never retire them. A service is decommissioned, but its key lives on. A contractor leaves, but a key they once copied is still valid. Make retirement a standard step in your decommissioning checklist: when a service is shut down, its keys are deleted the same day. Treat any key without an active consumer as a liability.

1

Born

Created with a descriptive name in the correct environment.

2

Placed

Stored in the secrets manager, with narrow access for one consumer.

3

Used and watched

Read at startup and monitored for failures and stray copies.

4

Rotated

Replaced on a schedule or after any event that could have exposed it.

5

Retired

Deleted in both Flagsmith and the secrets manager when its consumer disappears.

FArchitecture: Which Key Goes Where

A simple map of a typical system shows where each key belongs and where it must never appear.

The diagram below shows a typical product. On the left are the places that users can inspect: a web page in a browser and a mobile app on a phone. These use the public client-side ID. In the middle are your own backend services, running inside your infrastructure. They use server-side keys, loaded from a secrets store at startup. On the right is Flagsmith itself, which reads the key on every request to decide which environment is meant and how much trust to extend.

flowchart LR
  subgraph Untrusted["Places users can inspect"]
    Web["Web browser"]
    Mob["Mobile app"]
  end
  subgraph Trusted["Your protected infrastructure"]
    API["Backend API service"]
    Job["Background worker"]
    SM["Secrets manager"]
  end
  Web -- "client-side ID" --> FS["Flagsmith"]
  Mob -- "client-side ID" --> FS
  SM --> API
  SM --> Job
  API -- "server-side key" --> FS
  Job -- "server-side key" --> FS
  Admin["Engineer using the dashboard"] -- "login and roles" --> FS
Figure 2 — Public ID on the left, secret keys on the right, and humans on a separate login path.

The three kinds of caller

CallerCredentialWhat it is allowed to do
A browser or mobile appClient-side environment IDRead flags for an identity; possibly send that identity’s traits
A backend service or jobServer-side environment keyRead flags, download the environment document, report analytics
A human engineer or an automation that manages flagsDashboard login, or an administrative tokenCreate and edit features, segments, and environments, within role limits

Notice that the third caller uses a completely different credential. This separation is important: environment keys are for applications that consume flags, not for people or tools that manage them. If you find yourself wanting to use an environment key to change a flag, you are reaching for the wrong tool, and the answer is an administrative credential with its own permissions.

i
Remember

Backends sit in the trusted zone, but trust is not infinite. Containers get compromised, logs get shared, and engineers copy values into chat messages. The architecture limits the damage, and good habits, covered later, reduce the chance.

GAnatomy of an Authenticated Request

What actually happens, step by step, when an SDK presents a key? Following one request makes the whole security model concrete.

Every call from an SDK to Flagsmith carries the key in a request header, which is a small label attached to the message, like the address written on an envelope. Flagsmith reads the header first, before looking at anything else. From the key it learns two things at once: which environment the caller means, and which kind of key it is, which decides what the caller is permitted to do.

sequenceDiagram
  participant S as SDK
  participant F as Flagsmith Edge API
  S->>F: Request with the key in a header
  F->>F: Look up the key and find the environment
  F->>F: Decide the key type and its permissions
  alt Key unknown or revoked
    F-->>S: Rejected as unauthorised
  else Key allowed for this action
    F->>F: Evaluate or prepare the response
    F-->>S: Flags or the environment document
  else Key valid but action not allowed
    F-->>S: Rejected as forbidden
  end
Figure 3 — The decision Flagsmith makes on every request: who, which environment, and is this action allowed.

Three possible outcomes

1

Accepted

The key is known, belongs to a live environment, and its type permits the action. The caller gets its flags, or, with a server-side key, its document.

2

Unauthorised

The key is unknown, mistyped, or has been deleted. Flagsmith cannot tell who is asking and refuses. Typical causes are copy-and-paste errors, a revoked key, or a key from a different Flagsmith installation.

3

Forbidden

The key is valid, but it is the wrong kind for what was asked. The classic example is trying to download the environment document with the public client-side ID.

Reading the errors

These outcomes show up in your logs as familiar numeric codes, and learning to read them saves hours. An unauthorised result means “I do not recognise you”. Look for typos, trailing spaces, quotes accidentally included, a deleted key, or a key for the wrong installation. A forbidden result means “I recognise you, but you may not do that”. Look for the wrong key type, such as a client-side ID in a place that needs the server-side key. A sudden burst of either, from a service that worked yesterday, points to a recent key change or a deployment that picked up the wrong value.

Everyday analogy

A nightclub bouncer checks two things. First, is the ticket genuine and for tonight? If not, you are turned away at the door. Second, is it a general ticket or a backstage pass? A general ticket gets you to the dance floor; only the backstage pass opens the staff corridor. A general ticket held up at the staff corridor is not forged, it is simply not enough, and that is the difference between “unauthorised” and “forbidden”.

i
Tip

When debugging authentication problems, confirm in this order: is the key present, is it the exact string from the dashboard with no extra characters, does it belong to the environment you intend, and is it the right type for the SDK and mode you are using? Four checks, in that order, resolve almost every case.

Protecting the key in transit

A key must travel from your service to Flagsmith, and the journey needs protection. SDK traffic should always use an encrypted connection, known as TLS, which scrambles the contents so that anyone listening on the network sees only noise. The key lives in a request header, and encryption covers headers as well as content. Make sure your SDK is configured with a secure address, beginning with the secure web prefix, and that any internal proxy you pass through is configured not to downgrade the connection.

The less obvious danger is what intermediate systems record. Corporate proxies, load balancers, and observability agents sometimes log request headers for debugging. If they log the header that carries your key, the key is now sitting in a log system with many readers and long retention. Check what your network and monitoring tools capture, and configure them to redact the key header. Do the same for any tool that records outgoing requests from your services, such as tracing or debugging proxies.

!
Warning

“Verbose” or “debug” modes in HTTP libraries frequently print every header of every request. Never leave such modes on in production, and never paste their output into tickets or chats without first removing the key.

HChoosing the Right Key for Your Runtime

The right key depends on one thing: who can read the code that holds it. A short decision path settles it every time.

flowchart TD
  A["Where does the SDK run?"] --> B{"Can a user open or unpack this code?"}
  B -- Yes --> C["Use the client-side environment ID only"]
  B -- No --> D{"Do you need local evaluation or the full rulebook?"}
  D -- Yes --> E["Use a server-side key from a secrets manager"]
  D -- No --> F{"Is the environment variable or file protected?"}
  F -- Yes --> G["Server-side key is allowed, and preferred for backends"]
  F -- No --> H["Fix the storage first, or use the client-side ID"]
Figure 4 — A decision path for choosing which key to use.
RuntimeRight keyReason
Web page or single-page applicationClient-side IDAnyone can read the bundle and network calls
Mobile app (iOS, Android, cross-platform)Client-side IDApps can be unpacked and inspected by users
Desktop software shipped to customersClient-side IDDistributed binaries can be examined
Backend API in your cloudServer-side keyCode is private; local evaluation is available
Background worker or scheduled jobServer-side keyRuns in your infrastructure with protected configuration
Serverless functionServer-side key, injected securelyPrivate runtime; use the platform’s secret storage
Test suite in your CI pipelineTest environment key, or offline modeAvoid production keys in tests entirely
Server-rendered web app (rendering done on your server)Server-side key on the server; client-side ID for the browser partEach side uses what its audience may see

Backends that serve front ends

A common design is a front end that needs a few flag decisions, supported by a backend that already knows who the user is. There are two good ways to give the front end its flags. The first is to use a client SDK with the public client-side ID and let it ask Flagsmith directly. The second is to let the backend evaluate the flags with its server-side key and send the needed results to the front end as part of its normal response. The second approach keeps targeting rules, trait handling, and secrets entirely on your side, and is attractive when flag values contain anything you would rather not expose.

i
Remember

Some server-side SDKs can also be started with the public client-side ID, in which case they work only in remote evaluation mode. This is allowed, and sometimes useful for simple scripts, but you give up local evaluation. For real services, prefer the server-side key.

Hybrid applications and tricky cases

Real products rarely fit the neat table. A server-rendered web page is built on your server, but then runs in the browser. A desktop application is distributed to customers but talks to your backend. A mobile app may need flags before the user signs in. For each case, apply the same test: where does each line of code actually run, and who can read it there? Server-rendering code can use the server-side key, because it runs privately, but any flag logic that is shipped to the browser afterwards must use the client-side ID, or receive only the results already evaluated on the server.

Edge and serverless platforms deserve a second look. A function running at the edge of a content network is still code you deploy, so it can hold a server-side key, but many such platforms make environment variables visible to every engineer with deployment access. Check who can read those variables, and prefer the platform’s secret storage over plain settings. For desktop software, assume anyone can unpack the program: use only the client-side ID, and send sensitive decisions through your own authenticated backend.

A mobile app before sign-in

A retail app wants to show a seasonal banner on its launch screen, before anyone has signed in. It uses the client-side ID and an anonymous identity, such as a random installation identifier, to fetch the banner flag. After sign-in, it switches to the user’s opaque identifier, so targeting by plan or region becomes possible. At no point does the app contain a server-side key, and all sensitive decisions, such as pricing, are evaluated by the backend.

IExposure Risks of the Public Client-Side ID

The client-side ID is meant to be public, but “public” is not “harmless”. A careful designer knows exactly what the ID reveals.

Risk one: flag values are visible

Whatever the client SDK can read, a determined person can read, with or without your application. Anyone with the ID can ask what the flags and values are for an identity. This means that remote config values reachable by client SDKs must contain nothing secret. A value that says “show the new banner” is fine. A value that contains an access token, a private URL, or an internal price list is a leak waiting to be found. Keep secrets out of flag values altogether, and keep sensitive configuration in your own secured systems.

Risk two: anyone can invent an identity

The identity label is just text. A curious visitor can ask Flagsmith for the flags of any identity label they like, including labels belonging to real users, if those labels are guessable. If your identity labels are sequential numbers, a visitor can walk through them. Using opaque, unguessable identifiers instead of email addresses or small sequence numbers makes this guessing pointless, and prevents the labels from leaking personal information when they appear in network traffic.

Risk three: segment probing

If a client is allowed to send traits, a curious person can send different traits and watch how the answer changes. By trying “plan equals enterprise”, then “country equals DE”, and so on, they could work out the logic of your segments. This reveals your targeting design rather than breaking anything, but it is a real exposure for businesses that treat pricing tiers or experiments as confidential. Settings exist in the environment to limit what client SDKs may do, and the safest design for sensitive targeting is to evaluate on your server with the secret key, and send only results to the client.

Risk four: noise and abuse

Because the ID is public, someone can send large numbers of requests with it. That can consume your request allowance or create clutter in identity lists. Rate limiting at the platform, plus sensible monitoring on your side, keeps this manageable. For most organisations this is a theoretical annoyance rather than a daily problem, but it is worth knowing about.

Defence

No secrets in values

Treat every client-readable flag value as if it were printed on the page.

Defence

Opaque identifiers

Use random internal identifiers as identities, never emails, names, or guessable numbers.

Defence

Hide disabled flags

Environment settings let you stop disabled flags being returned to SDKs, so unreleased features do not leak their names.

Defence

Evaluate sensitive logic server-side

Send only the final result to the browser, and keep the rules and traits in your backend.

!
Warning

Flag names themselves can leak plans. A flag called “launch_acquired_competitor_integration” returned to every browser tells the world what you are building. Use neutral, boring names for sensitive unreleased work, and enable the setting that hides disabled flags from SDK responses.

Putting it together

A fintech wants to roll out a new fee schedule by customer tier. The tier rules and percentage splits are confidential. Instead of sending traits from the browser, the backend uses its server-side key, evaluates locally with the customer’s tier, and returns a single decision to the page: “show schedule B”. The browser never learns the rules, never sees the traits, and never needs more than a boolean. The client-side ID is still used for harmless, public features such as a new button style.

Questions to ask before exposing a flag to clients

Before a flag becomes readable by client SDKs, a quick set of questions prevents most exposure problems. Would I be comfortable if this flag’s name and value appeared in a newspaper? Does the name hint at an unreleased product, a customer, or a partnership? Does the value contain anything that could be misused, such as an address, a token, or a threshold that reveals a business rule? Does a segment targeting this flag rely on traits that a visitor could guess and try? If any answer is uncomfortable, move the decision to the server and send only the outcome.

Flag typeSafe for clients?Better design
Show or hide a new buttonYesNone needed
Choose a colour theme variantYesNone needed
Name hints at an unreleased productRiskyUse a neutral name and hide disabled flags
Value holds an internal address or tokenNoKeep the secret in your backend and flag only the behaviour
Pricing or discount rules by customer tierRiskyEvaluate on the server and return only the result
Permission to use a paid featureOnly as a hintAlways enforce again on the server

JWhen a Server-Side Key Leaks: The Blast Radius

Security people talk about “blast radius”: how much damage one mistake can do. Knowing the radius of a leaked server-side key tells you how urgently to react.

What an attacker gains

Holding a server-side key, an outsider can download the environment document and read the full targeting rulebook for that one environment. They can see segment definitions, identity overrides, percentage splits, flag values, and the names of every feature, including ones not yet released. They can also ask Flagsmith to evaluate flags for any identity, and may be able to send analytics events, which could pollute your usage statistics.

What an attacker does not gain

The key is a consumer credential. It does not let the holder edit features, change segment rules, switch flags on or off, add team members, or touch other environments. This is a vital limit. A leaked key exposes knowledge, but it does not hand over control of your production behaviour. People sometimes panic on the wrong grounds, imagining that an intruder could flip flags and break production. That is not what this key allows; for that, an attacker would need a dashboard login or an administrative token, which are guarded separately.

QuestionLeaked server-side keyLeaked client-side ID
Can they read your targeting rules?Yes, in fullNo, only per-identity results
Can they read flag values?All of themThose returned for an identity
Can they change a flag?NoNo
Can they reach other environments?NoNo
Is it urgent to replace?Yes, promptlyRarely
Main harmDisclosure of business logic and unreleased plansMinor noise; limited data exposure by design

Indirect consequences worth thinking about

The harm from knowing your rulebook can still be serious. A competitor learning about an unreleased feature, a journalist discovering a pricing experiment, or a malicious user finding the exact conditions under which a safety check is disabled: all are realistic concerns. Rules that mention specific customer identifiers in overrides could also reveal who your beta customers or key accounts are. And where flags guard security-relevant behaviour, such as a weaker check for internal testers, knowing the rule helps an attacker design an attack that fits it.

Everyday analogy

Imagine someone steals the keys to a cinema’s projection booth. They cannot rewrite the film or change what the audience sees tonight, but they can read the schedule for next month’s unreleased premieres and the guest list for the private screenings. Annoying, possibly costly, but different in kind from someone taking over the projector. Still, you would change the locks the same day.

!
Warning

“It cannot change flags” is not a reason to relax. A key that keeps working forever, hidden in an old repository, will eventually be found by someone you did not choose. Treat every confirmed exposure as an incident, and replace the key.

Estimating the damage in your own organisation

The right level of urgency depends on what your rulebook contains. Walk through a short assessment for the affected environment. How many features does it hold, and are any unreleased or commercially sensitive? Do segment rules encode pricing, eligibility, or fraud checks? Do identity overrides name individual customers or staff? Do any flags weaken a safety or security check for testers? A rulebook full of harmless interface experiments is a small disclosure; one that encodes confidential pricing or security exceptions is a large one, and may justify informing other teams or leadership.

Write the answers down as part of the incident record. They guide the response and also serve as a useful design review. If the assessment shows that sensitive rules sit in an environment read by many services, consider splitting them: keep confidential targeting in a separate project with fewer consumers, so a leak of one key reveals less. Smaller rulebooks with fewer holders are naturally safer, and this is one of the quiet benefits of keeping projects focused.

KEnvironment Keys vs Administrative Credentials

Flagsmith has more than one kind of secret. Keeping them straight prevents both over-powered applications and under-powered automation.

Environment keys, client-side or server-side, exist so that applications can read flags. A separate family of credentials exists so that people and tools can manage them. These include the dashboard login of each user, protected by whatever sign-in method your organisation uses, and administrative tokens or API keys that scripts and pipelines can present to the management interface. The permissions are different, the storage rules are different, and mixing them up in either direction is a design error.

CredentialUsed byPurposePower
Client-side environment IDBrowsers, mobile appsRead flags for an identityLowest, public
Server-side environment keyBackend servicesRead flags and the environment documentMedium, secret
Dashboard loginPeopleManage flags within assigned rolesRole-based, personal
Administrative token or API keyAutomation and scriptsManage flags, environments, and settings programmaticallyHigh, secret, tied to a user or an organisation

Two common design errors

Error

Management credentials in applications

Putting an administrative token inside a service so it can “just check a flag” gives that service the power to change everything. Applications need environment keys, not management power.

Error

Environment keys in management tools

Trying to use a server-side key in a script that creates flags will be refused, as it should be. Use a proper administrative credential, stored just as carefully.

Good

Separate lifecycles

Environment keys rotate with deployments. Administrative tokens rotate with staff changes and tooling changes. Keep the two lifecycles apart.

Good

Least privilege everywhere

Give each credential only the smallest set of powers its job needs, and name it so its purpose is obvious.

i
Remember

The exact names and options for administrative credentials depend on your plan and version, so read the current documentation for the management interface. The principle is stable: management credentials are more powerful than environment keys and deserve at least as much care.

An automation example

A team wants a nightly job that creates a flag in staging whenever a feature branch is opened. The job needs to create features, which is management, so it uses an administrative token stored in the CI system’s secret store. The staging application, which merely reads the new flag, uses its own staging server-side key. Two credentials, two purposes, and neither can do the other’s job.

LCreating and Naming Keys

Good key hygiene starts at creation. A few minutes of care here saves hours during an incident.

1

Decide the consumer

Which service or job will use this key, and in which environment? One key should serve one consumer. If two services need access, create two keys.

2

Open the right environment

In the dashboard, select the project and the environment first. Double-check the environment name, since a key created in the wrong place works perfectly and silently.

3

Create with a meaningful name

Use a pattern such as service, then environment, for example “checkout-prod”. Add a short note if the interface allows, explaining the owner and purpose.

4

Copy straight into the vault

Paste the value directly into your secrets manager. Do not paste it into chat, email, tickets, or a notes file, even briefly.

5

Grant narrow access

Allow only the identity of the consuming service to read the secret. Developers do not need to read production values to deploy.

6

Record the key in an inventory

Write down the key’s name, owner, purpose, creation date, and where it is stored. Never record the value itself in the inventory.

A naming convention that lasts

Choose a consistent pattern and document it. A good pattern contains three pieces of information: the consumer, the environment, and, where you rotate keys, a generation marker. For example, “checkout-api-prod-2026a” tells a future engineer which service uses it, which environment it points at, and that it is the first key of 2026. When you rotate, the new key becomes “checkout-api-prod-2026b”, and the old one is easy to identify and delete.

Include

Consumer

The service, job, or pipeline that uses the key, so you know whom to talk to before revoking it.

Include

Environment

Production, staging, or development spelled out, to catch mix-ups when reading logs and configurations.

Include

Generation

A simple letter or date so old and new keys can coexist during rotation without confusion.

Avoid

Personal names and “test”

Names such as “dave-test” or “temp” tend to become permanent, and nobody dares to delete them.

i
Tip

Create a separate key for each developer-facing sandbox, scoped to a development environment. When a laptop is lost or a developer leaves, you can delete their sandbox key without touching anything that real users depend on.

Who may create and see keys?

Not everyone with dashboard access needs the ability to create or reveal server-side keys. Use the roles and permissions available in your plan to limit this power to a small group, such as platform and security engineers. Developers may need to see the client-side ID, which is public, but have little reason to view production server-side keys. If your process requires a developer to create a key, use a short, documented request flow, so every key has an owner and a record from the start. Keeping creation rights narrow also narrows the number of people who could ever have seen a secret, which makes investigation much simpler after an incident.

i
Tip

Make “create a key” a small, repeatable procedure, with a template for the name, a place to record the owner, and a checklist for storage. A boring, standard process produces consistent keys, and consistent keys are far easier to audit, rotate, and revoke.

MStoring Keys Safely

A secret is only as safe as the place where it sleeps. Here are the good places, the poor places, and the dangerous ones.

The golden rule of secrets is that they should never be written into anything that travels: source code, container images, build artifacts, documents, chat messages, or screenshots. Instead, they are kept in a dedicated store and delivered to the running service at the last possible moment, in memory, through an identity that the platform controls.

WhereVerdictWhy
A managed secrets service such as AWS Secrets ManagerBestEncrypted at rest, access controlled by identity, audited, supports rotation
A parameter store with encrypted valuesGoodSimple and cheaper, with access control and encryption when configured properly
A vault product run by your teamGoodPowerful and flexible, but you operate it, so availability and security are yours
Orchestrator secrets, such as Kubernetes SecretsAcceptable with careValues are encoded, not necessarily encrypted, unless encryption at rest and tight access are set up
CI system secret storeGood for pipelinesKeeps secrets out of repositories and masks them in logs when used correctly
Environment variable set by the platform from a secret storeGoodThe usual way a service receives its key at start
A configuration file in the repositoryNeverSpreads to every clone, fork, and backup
A container image or build artifactNeverAnyone who can pull the image can read the key
Chat, email, tickets, wikisNeverUnlimited copies, long retention, many readers

How the key travels to the service

sequenceDiagram
  participant D as Deployment platform
  participant SM as Secrets manager
  participant T as Service task
  participant F as Flagsmith
  D->>T: Start task with its own identity
  T->>SM: Ask for the Flagsmith key using that identity
  SM->>SM: Check the task identity may read this secret
  SM-->>T: Return the key into memory
  T->>F: Start SDK and make requests with the key
  Note over T,SM: The key never appears in code, images or logs
Figure 5 — The key reaches the service through its identity, at runtime, and only into memory.

Local development

Developers need keys too, but they do not need production keys. Give each developer, or each shared sandbox, access to a development environment with its own keys. Keep those in a local file that is excluded from version control, or in a developer-friendly secrets tool. Make sure the project’s ignore rules cover such files, and add an automated check that blocks commits containing key-shaped strings. Production keys should be available only to production workloads, never to individual laptops.

!
Warning

Deleting a secret from the latest version of a repository does not remove it from history. Anyone who clones the repository can still find the old commit. If a key has ever been committed, treat it as leaked and replace it, whatever you do to the code afterwards.

Containers, orchestrators and pipelines

Container platforms add special cases. Images are shared widely and cached on many machines, so a key must never be baked into an image; it should arrive when the container starts. Orchestrators such as Kubernetes offer built-in secret objects, but by default these are merely encoded, not strongly protected, so enable encryption at rest, restrict who can read them with access rules, and consider a tool that synchronises values from a real secrets manager into the cluster at runtime. Prefer mounting a secret as a file or injecting it as an environment variable at start, and avoid placing it in a configuration map, which is designed for non-sensitive values and is often more widely readable.

Continuous integration pipelines need keys too, for tests and deployments, and they are a favourite target for attackers, because they run code from many contributors. Store pipeline secrets in the pipeline system’s own secret store, scope each secret to the jobs and branches that truly need it, and never expose secrets to builds triggered from untrusted forks. Use test-environment keys in test jobs, and keep production keys available only to the deployment job that actually needs them. Turn on masking so that accidental printing of a secret appears as asterisks in logs.

Container

Inject at start

Pass the key into the container when it starts, never into the image build.

Cluster

Encrypt and restrict

Enable encryption at rest for cluster secrets and limit read access to the services that need them.

Pipeline

Scope narrowly

Expose a secret only to the job and branch that needs it, never to builds from untrusted forks.

Pipeline

Mask outputs

Ensure secrets are masked in logs, and avoid commands that echo environment variables.

NFramework and Build-Tool Pitfalls

Many leaks happen not through carelessness, but through a build tool doing something helpful that nobody noticed.

Modern front-end frameworks make it easy to use environment variables in your code. To prevent accidental exposure, most of them follow a convention: only variables with a special prefix are copied into the browser bundle, and everything else stays on the server. Conventions of this kind include prefixes such as REACT_APP_, NEXT_PUBLIC_, and VITE_. The prefix means “this value is allowed to be public”. The danger is easy to see: if a developer names the server-side Flagsmith key with a public prefix, the build tool dutifully places it in the downloadable bundle, and the secret ships to every visitor.

Trap

Public prefix on a secret

A secret named with a “public” prefix is copied into the front-end bundle by design. The tool is working correctly; the name was wrong.

Trap

Server code in the browser bundle

Frameworks that mix server and browser code can include a module in the wrong place if imports are careless. Check which files end up in the shipped bundle.

Trap

Source maps

Published source maps can make it easy to read the original code, including any value that was compiled in.

Trap

Mobile app configuration

Anything inside an app package can be extracted. A secret in the app’s settings file is a secret that every user can read.

A safe way to name things

Adopt a naming scheme that makes the type of key obvious from its variable name. For example, name the public one with the word “public” or “client” in it, and the secret one with the word “secret” or “server”. A reviewer reading a change can then spot an error at a glance: a variable with “secret” in its name and a public prefix is a red flag. Combine this with automated checks that scan the built front-end bundle for the secret key’s prefix before every release.

1

Name by sensitivity

Names should say whether a value is public or secret, so mistakes are visible in code review.

2

Separate front-end and back-end settings

Keep the two in different files and different pipelines, so a secret has no path into a browser build.

3

Scan the build output

After building, search the produced files for the server-side key prefix and fail the build if it appears.

4

Review the network traffic

Open the browser’s developer tools on a test build and check which keys appear in requests. Only the public ID should be there.

i
Tip

A quick manual test works wonders: load your own site, open the page source and developer tools, and search for the first characters of your server-side key’s prefix. If the search finds anything, you have just saved yourself an incident.

ORotating Keys Without Downtime

Rotation means replacing a key on purpose, before anyone forces you to. Done well, nobody notices; done badly, production goes dark.

Rotation sounds frightening because the obvious way to do it is dangerous: delete the old key and hope the new one is deployed in time. Flagsmith’s support for several server-side keys per environment makes a much safer way possible. You create the new key first, while the old one still works. You deploy the new key to every consumer. Only when every consumer has switched do you delete the old one. At every moment, every service has at least one working key.

sequenceDiagram
  participant Ops as Engineer
  participant FS as Flagsmith Dashboard
  participant SM as Secrets manager
  participant Svc as Service instances
  Ops->>FS: Create a new key for the same environment
  Ops->>SM: Store the new key as the next version
  Ops->>Svc: Roll out so instances load the new key
  Svc->>FS: Requests now use the new key
  Ops->>FS: Confirm the old key is no longer used
  Ops->>FS: Delete the old key
  Ops->>SM: Remove the old secret version
Figure 6 — Overlap makes rotation safe: new key first, old key last.

The rotation steps in plain words

1

Create the new key

Add a second server-side key to the same environment, named with the next generation marker.

2

Store it

Put the new value in the secrets manager as a new version, leaving the old version in place for the moment.

3

Roll it out

Restart or redeploy the consuming services so they read the new value. Roll gradually and watch for authentication errors.

4

Verify

Confirm from your own metrics that no instance still uses the old key. Look at deployment versions and at the document refresh success rate.

5

Delete the old key

Remove the old key in the dashboard and the old version in the secrets manager. Rotation is complete only when the old key is gone.

How often?

There is no single right schedule. A common starting point is once or twice a year for routine rotation, and immediately after any suspected exposure, any departure of someone with access to production secrets, or any change of tooling that touched the storage. What matters more than frequency is practice. A team that has rotated a key calmly three times will do it well in an emergency. A team that has never done it will discover its hidden dependencies, such as a forgotten script with the old key pasted in, at the worst possible moment.

i
Remember

Long-running processes that read their key at startup will not notice a new value until they restart. Local evaluation clients keep using the key they started with. Plan the rollout so that all instances restart before you delete the old key.

i
Tip

If your secrets manager supports scheduled rotation, you can automate the storage side. You still need a deliberate step that creates the new key in Flagsmith and removes the old one, so write that step as a small, tested script using an administrative credential, and keep it in your runbook.

How rotations go wrong

Most rotation failures come from a small set of causes, all avoidable. The first is the forgotten consumer: a script, a cron job, or a staging service still using the old key, which breaks the moment it is deleted. Avoid this by naming keys per consumer, so the old key’s name tells you exactly whom to check, and by watching authentication failures after each step. The second is the stale process: a long-running service that read the old key at startup and never restarted, so it keeps using a key you are about to delete. Avoid it by restarting every consumer and confirming from deployment records that none was missed.

The third is deleting too early: removing the old key the moment the new one is created. The fourth is caching in unexpected places: a secrets cache, a sidecar, or a configuration service that keeps handing out the old value for a while. Each of these is easy to fix once you know it exists. The surest way to find them is a rehearsal in a safe environment, where a failure costs a little time and nothing else.

FailureSymptomPrevention
Forgotten consumerA job or service starts failing after deletionOne key per consumer; check failures by key name before deleting
Stale processErrors appear hours later when an old process refreshesRestart everything and verify versions
Deleting too earlyImmediate authentication errors across servicesDelete only after verification
Cached secretNew key stored, old key still servedKnow your caches and clear them as part of the plan
Wrong environmentStaging breaks or production reads staging flagsName keys with environment; log it at startup

PIncident Response: When a Key Is Exposed

Nobody plans to leak a key, but everybody should plan for it. A short, rehearsed runbook turns panic into procedure.

flowchart TD
  A["Suspected or confirmed exposure"] --> B{"Which key type?"}
  B -- "Client-side ID" --> C["Low urgency: review exposed values and settings"]
  B -- "Server-side key" --> D["Create a replacement key now"]
  D --> E["Deploy the replacement to all consumers"]
  E --> F["Delete the exposed key"]
  F --> G["Review the audit log and access records"]
  G --> H["Assess what the rulebook revealed"]
  H --> I["Fix the cause and write the lessons down"]
  C --> I
Figure 7 — The response path: replace first, investigate second, learn always.

The first hour

1

Confirm what leaked

Identify the exact key, its environment, and where it was exposed. Is it a client-side ID, which is low risk, or a server-side key, which is not?

2

Create a replacement first

Make a new key and deploy it to all consumers, so that deleting the old one will not cause an outage.

3

Delete the exposed key

Revoke it in the dashboard. From that moment, anyone holding the old value is refused.

4

Clean up the exposure

Remove the key from the place where it leaked, such as a repository, a ticket, or a log, remembering that history and copies may persist.

5

Check for changes

Review the audit log for any unexpected flag or setting changes, in case a separate credential was also exposed.

The next days

After the urgent steps, ask what the rulebook revealed. Were there overrides naming specific customers? Were there unreleased features whose names are sensitive? If so, decide who needs to be told: product owners, account teams, or, in regulated sectors, compliance staff. Then find the root cause. Was the key pasted into a public repository? Did a build tool bundle it into a front end? Was a log level set too high? Fix that cause, add an automated check so the same mistake is caught earlier next time, and record the incident briefly in a shared place, without including the key.

!
Warning

Do not delete the exposed key before the replacement is deployed, unless you are certain the exposure is being actively abused and a short outage is the lesser evil. Deleting first can turn a disclosure incident into an availability incident, and both are costly. In most cases, replace first, then revoke, within minutes.

Everyday analogy

If a house key goes missing, a sensible person has the new lock fitted and new keys cut for everyone in the household, and only then throws away the old keys. Changing the lock without giving the family new keys would leave them standing in the street. The order of operations is what makes it a repair, not a second problem.

QDetecting Problems: Scanning, Logs and Alerts

The best incident is the one you catch within minutes. A handful of automated checks do most of the catching.

Catch secrets before they leave

Secret scanning tools look for strings that match known key shapes. They can run on a developer’s laptop before a commit, in your continuous integration pipeline before a merge, and across the history of existing repositories. Many code hosting platforms also offer built-in scanning that alerts you when a recognised secret appears. A recognisable prefix on server-side keys helps these tools find them reliably. Turn the scanning on, route its alerts to a person who will act, and treat each alert as real until proven otherwise.

Watch the signals that point to key trouble

SignalWhat it may meanAction
Sudden rise in authentication failuresA revoked, mistyped, or rotated key still in use somewhereFind which service sends them, and fix its configuration
Rise in “forbidden” resultsA client-side ID used where a server-side key is requiredCorrect the key type in that deployment
Document refresh failures in local modeKey problem or network problemCheck key validity, then connectivity
Requests from unexpected placesA key in use outside your infrastructureCompare sources with your known ranges; rotate if unexplained
Secret scanner alertA key committed, logged, or posted somewhereTreat as exposure; follow the runbook
Unexpected flag changes in the audit logA compromised login or administrative tokenRevoke those credentials; review all recent changes

Logs that help and logs that hurt

Your own services should log that authentication failed, which key name or consumer was involved, and when. They must never log the key itself, nor print configuration objects that contain it. A surprising number of leaks come from debug output that dumps all settings during a failure, exactly when engineers are most likely to paste logs into a ticket for help. Mask secrets in configuration printouts, and configure your logging tools to redact values that match your key shape.

i
Tip

Because you name keys by consumer, you can attach the key name to your metrics. A graph of “authentication failures by key name” shows within seconds which service is struggling after a rotation, instead of leaving you to guess from a pile of identical errors.

A sample key inventory

An inventory need not be fancy. A simple table in a shared, access-controlled document is enough, as long as it is kept current and never contains the key values. The columns that matter are the key’s name, the environment, the consumer, the owner, the storage location, the creation date, and the date of the last rotation.

Key nameEnvironmentConsumerOwnerStored inLast rotated
checkout-api-prod-2026aProductionCheckout servicePayments teamSecrets manager, production accountSpring
catalogue-api-prod-2026aProductionCatalogue serviceSearch teamSecrets manager, production accountSpring
reports-job-stg-2026aStagingReporting jobData teamSecrets manager, staging accountWinter
edge-proxy-prod-2026aProductionEdge ProxyPlatform teamSecrets manager, production accountSpring

Reviewing this table each quarter takes minutes and answers the questions that matter in an emergency: who owns each key, where it lives, and how old it is. It also makes it obvious when a key has no owner, which is the signal to investigate and probably delete.

REnvironments and Key Hygiene

Separate environments are only separate if their keys stay separate. The discipline is simple, and it pays back every day.

flowchart LR
  subgraph Dev["Development environment"]
    DK["Dev keys"] --> DS["Developer sandboxes and local runs"]
  end
  subgraph Stg["Staging environment"]
    SK["Staging keys"] --> SS["Staging services and automated tests"]
  end
  subgraph Prod["Production environment"]
    PK["Production keys"] --> PS["Production services only"]
  end
  Dev -. no key crosses over .- Stg
  Stg -. no key crosses over .- Prod
Figure 8 — Each environment has its own keys, and each key stays in its own territory.

Rules that keep environments apart

Rule

Production keys stay in production

No laptop, no test suite, and no staging service should ever hold a production key. If it must read production flags, question why.

Rule

Tests use test environments

Automated tests use a dedicated environment, or offline mode, so they cannot change or read live behaviour.

Rule

Name everything with the environment

Keys, secrets, and variables carry the environment in their names, so a mix-up is visible at a glance.

Rule

Check the environment at startup

Have services log which environment their key points to, so a staging service with a production key is spotted immediately.

Short-lived environments

Teams that create a temporary environment for each feature branch or pull request face a special case. Each temporary environment gets its own keys, and those keys should be created automatically, given a short life, and deleted when the environment is torn down. Orphaned keys from forgotten environments are a quiet source of risk, because nobody remembers they exist. Include key cleanup in the same automation that removes the environment, and review the key list regularly for unfamiliar names.

i
Remember

A key inventory is the cure for forgotten keys. A simple table listing each key’s name, environment, owner, purpose, and creation date lets you spot keys with no owner and keys that have lived for too long. Review it every quarter.

A worked example: onboarding a new service

To see these rules in motion, imagine a team launching a new “notifications” service. In the first week, they create three server-side keys: “notifications-dev-2026a” in the development environment, “notifications-stg-2026a” in staging, and “notifications-prod-2026a” in production. Each is stored in the secrets manager of the matching account, readable only by that service’s role. The developers’ laptops use the development key through a local, ignored configuration file. The test pipeline uses the staging key, injected by the pipeline’s secret store, and masked in logs.

At launch, the production key is read only by the production containers. At startup, the service logs the name of the environment its key points to, and the platform team confirms it says production. Three months later, the team records the first rotation in the inventory. A year later, when the service is retired, all three keys are deleted on the same day as the containers. At no point did anyone email a key, paste it into a document, or share one key between environments, and the process cost only a few extra minutes at each stage.

SEdge Proxy, Self-Hosting and Multi-Region Setups

Bigger and more controlled deployments add new places where keys appear. Each needs the same care.

Self-hosted Flagsmith

If you run Flagsmith yourself, environment keys work exactly as described, but the service they point at is yours. The SDKs are given your own API address in addition to the key. Because you also control the database and the servers, you are responsible for protecting the stored keys, for backing up the data that contains them, and for securing the connection between the SDKs and your installation. Use encrypted connections between clients and the server, restrict network access to the management interface, and handle backups of the database as sensitive material, since a backup contains the same secrets as the live system.

The Edge Proxy

An Edge Proxy is a lightweight service placed inside your network to cache environment data and answer SDK requests close to your applications. To do its work, the proxy itself must be configured with the keys of the environments it serves, typically a server-side key, which it uses to fetch environment data, and the matching client-side ID, which it uses to recognise client requests. The proxy therefore becomes a new holder of secrets, and must be treated as one. Store its configuration in your secrets manager, restrict who can read it, and rotate its keys together with the rest.

SetupWho holds the server-side key?Extra care needed
Flagsmith Cloud, directEach backend serviceSecrets manager access per service
Flagsmith Cloud via Edge ProxyThe proxy, and optionally the servicesProtect the proxy’s configuration; limit who can reach it
Self-hosted, directEach backend serviceProtect the database and its backups too
Self-hosted with proxyThe proxyBoth of the above
Multi-region deploymentsServices in each regionConsistent rotation across regions, region-scoped secret access

Multiple regions and clusters

When the same service runs in several regions, you can use one server-side key for all of them, or one per region. Separate keys per region make it easy to see where traffic comes from and to revoke one region without touching the others, at the cost of more keys to manage. Whichever you choose, rotate in a rolling order, region by region, and make sure each region’s secrets store is updated before its services restart.

!
Warning

Check the current documentation for how your version of the proxy and your SDKs expect keys to be supplied. Details such as option names and supported plans change over time, and a misconfigured proxy can quietly serve the wrong environment’s data.

TDesign Patterns and Anti-patterns for Keys

A few shapes of use keep you safe. A few other shapes appear again and again in incident reports.

Patterns worth adopting

Pattern

One key per consumer

Every service and job gets its own named key, so revocation is surgical and tracing is easy.

Pattern

Secrets by identity

Services read keys from a secrets manager using their own platform identity, not a shared password.

Pattern

Backend-evaluated sensitive flags

Confidential targeting is evaluated on the server and only results reach the browser.

Pattern

Overlap rotation

New key before old key, with deletion last, so no service ever goes without.

Pattern

Key inventory

A simple register of every key, its owner, and its purpose, reviewed regularly.

Pattern

Automated bundle scan

Every front-end build is scanned for secret prefixes before it can be released.

Anti-patterns to avoid

ANTI-PATTERN 01Avoid
What it is

Using the server-side key inside a browser bundle or mobile app.

Why it hurts

Every user receives a copy of the key, and with it the ability to download your whole targeting rulebook.

Do this instead

Use the client-side ID in clients, or evaluate on your server and send results.

ANTI-PATTERN 02Avoid
What it is

One shared key for every service, environment-wide, kept in a team document.

Why it hurts

You cannot tell who uses it, you cannot revoke it without breaking everything, and every reader of the document holds production access.

Do this instead

Create one key per consumer and keep each in the secrets manager.

ANTI-PATTERN 03Avoid
What it is

Putting secrets, tokens, or private addresses inside flag values that clients can read.

Why it hurts

The client-side ID is public, so anyone can read those values. Remote config is for tuning behaviour, not for storing secrets.

Do this instead

Keep real secrets in your secrets manager and use flags only to choose between behaviours.

ANTI-PATTERN 04Avoid
What it is

Never rotating, and never practising rotation.

Why it hurts

Old keys spread into forgotten scripts and laptops. When an emergency arrives, the team discovers hidden dependencies under pressure.

Do this instead

Rotate on a schedule, using overlap, and rehearse the emergency path at least once a year.

ANTI-PATTERN 05Avoid
What it is

Using production keys in tests, staging, or on laptops “just to check something”.

Why it hurts

Production keys then live in many places that have weaker controls, and a mistake in a test can touch production data and analytics.

Do this instead

Give each stage its own environment and keys, and let production keys exist only in production.

A pattern for sensitive targeting: split the project

One powerful design is to separate flags by sensitivity. Put everyday interface experiments in one project, readable by many services and by client SDKs. Put confidential targeting, such as pricing logic or eligibility rules, in a second project, readable only by one or two trusted backend services, and never by clients. Each project has its own environments and keys, so the keys for the sensitive project exist in far fewer places. If a key for the everyday project leaks, little of value is revealed; if a key for the sensitive project is ever at risk, the list of places to check is short and well known.

i
Remember

Security is often about reducing how many places hold a secret and how much that secret reveals. Splitting projects by sensitivity does both at once, with no new technology, only a deliberate way of organising what you already have.

UBest Practices Checklist and Testing Your Setup

A checklist you can run through each quarter, plus a few tests that prove your key handling actually works.

Habits that protect you

  • Server-side keys only in protected backends
  • Client-side ID only in clients
  • One named key per consumer and environment
  • Secrets manager with identity-based access
  • Secret scanning on commits and pipelines
  • Rotation with overlap, practised regularly
  • Opaque identifiers and no secrets in flag values
  • A written incident runbook

Mistakes that hurt

  • Confusing the two key types
  • Public prefixes on secret variables
  • Keys in repositories, images, or chat
  • One shared key everywhere
  • Production keys on laptops or in tests
  • Logging configuration objects
  • Deleting the old key before deploying the new
  • Forgotten keys with no owner

Tests that prove it works

1

Bundle scan test

Build the front end and search the output for the server-side prefix. The test fails the build if anything is found.

2

Wrong-key test

In a test environment, try to download the environment document with the client-side ID and confirm it is refused. This proves the permission boundary you rely on.

3

Rotation rehearsal

In staging, perform a full overlap rotation, and confirm no authentication errors appear and the old key is gone at the end.

4

Revocation test

Delete a throwaway key and confirm the service using it fails in the way you expect, with a clear alert, and recovers when given a new key.

5

Log redaction test

Trigger an error with debug logging on and confirm that no key value appears in any output.

i
Tip

Turn the checklist into a recurring calendar item with a named owner. Security work that depends on someone remembering usually fails; security work that appears in a calendar and ends in a short written note tends to survive staff changes.

A quarterly review agenda

Set aside thirty to sixty minutes each quarter, with security and platform engineers in the room, and walk through the same short agenda every time. Repetition is the point: a familiar agenda is quick, and gaps stand out.

1

Review the inventory

Check every key has an owner, a consumer, and a recent rotation date. Delete anything unexplained.

2

Review access

Check who can read production secrets and who holds administrative credentials. Remove anyone who no longer needs access.

3

Review scanner results

Look at secret scanning alerts since the last review, and confirm that each one was handled and its key replaced.

4

Review the audit log

Skim flag and setting changes for anything unexpected, especially from automation credentials.

5

Plan the next rotation

Decide which keys are due, assign owners, and book the rehearsal if it is overdue.

VReal-World and Industry Examples

The split between a public identifier and a secret key is not unique to Flagsmith. It is one of the most common ideas in modern software, and the failures follow familiar patterns too.

Stripe: publishable and secret keys

The payment company Stripe gives each account a publishable key, meant to be embedded in web pages and apps, and a secret key, meant only for servers. The publishable key can only perform limited actions, such as collecting card details into a safe token. The secret key can do far more, including moving money. This is the same design as Flagsmith’s pair, and the same advice applies: the public one may travel, the secret one may not.

Firebase and mapping services: public keys with guard rails

Google’s Firebase documentation explains that the web configuration values shipped with an app identify a project but do not by themselves grant access; security is enforced by separate rules on the server side. Mapping services similarly issue keys that are embedded in web pages, then restrict where those keys may be used. The pattern repeats: a public identifier travels widely, and protection lives in what that identifier is allowed to do.

Uber, 2016: credentials in a repository

In a widely reported 2016 incident, attackers gained access to a private code repository used by Uber engineers, found cloud access credentials stored there, and used them to reach data on tens of millions of people. The lesson for every secret, including a Flagsmith server-side key, is that code repositories are poor safes. Even a private repository can be reached through a stolen login, so credentials should live in a secrets manager.

Toyota, 2022: a key that waited for years

Toyota reported in 2022 that part of the source code for a customer service had been publicly accessible on a code hosting platform for years, and that it contained an access key which could have exposed data for hundreds of thousands of customers. The key had sat in public view for a long time before anyone noticed. It shows why secret scanning and key inventories matter: a leaked key does not announce itself, and it keeps working until someone deletes it.

A common front-end story

Security researchers regularly publish reports of companies whose websites quietly included private keys in their JavaScript bundles, often because a secret was given a “public” variable prefix. These findings are rarely about malice; they are about an innocent build setting. The defence is the one in this guide: name keys by sensitivity, separate front-end and back-end settings, and scan the built output.

An illustrative setup on AWS

To bring everything together, here is one typical arrangement for a product running on Amazon Web Services. It is an example of how the pieces fit, not a required recipe. The single-page front end is served from a content delivery network and carries only the public client-side ID. The backend runs as containers on Amazon ECS. Each service has its own server-side key, stored as a secret in AWS Secrets Manager, and each task role may read only its own secret. Metrics for authentication failures, labelled by key name, flow to Amazon CloudWatch, with alarms. A scheduled rotation job creates a new key in Flagsmith, stores it as a new secret version, triggers a rolling restart, and deletes the old key after verification.

flowchart LR
  U["Users"] --> CDN["Content delivery network with the front end"]
  CDN -- "client-side ID only" --> FS["Flagsmith"]
  U --> ALB["Application Load Balancer"]
  ALB --> T1["ECS task: checkout service"]
  ALB --> T2["ECS task: catalogue service"]
  SM["AWS Secrets Manager"] --> T1
  SM --> T2
  T1 -- "its own server-side key" --> FS
  T2 -- "its own server-side key" --> FS
  T1 --> CW["CloudWatch metrics and alarms"]
  T2 --> CW
  Rot["Rotation job"] --> SM
  Rot --> FS
Figure 9 — An illustrative AWS layout: public ID in the browser, one secret per service, and an automated rotation job.
i
Tip

In this layout, the rotation job needs an administrative credential, which is a different and more powerful secret than the environment keys. Give that credential its own narrowly scoped role, store it separately, and monitor its use closely.

What the incidents have in common

Looking across the examples above, a few patterns repeat. The secret was in the wrong place: a repository, a public bundle, a log. Nobody noticed for a long time, because a leaked key does not announce itself. The damage came from reach: the key could do more than its holder needed. And the fix, once discovered, was always the same: replace the key and find the cause.

Each pattern has a matching defence in this guide. For the wrong place, use a secrets manager and scan builds. For the long silence, use scanners, alerts, and a quarterly review. For excessive reach, create narrow keys per consumer in one environment, and remember that Flagsmith’s own design limits what a server-side key can do. None of these defences is exotic; they are routine habits, and the incidents are reminders of what happens when the habits are skipped.

WFrequently Asked Questions

Short answers to the questions that come up most often about environment keys.

Q1What is the difference between the client-side ID and the server-side key?
The client-side ID is a public identifier that lets browsers and apps ask for the flags of one identity. The server-side key is a secret credential that lets backends read flags and download the full environment document for local evaluation. The first may be exposed; the second must never be.
Q2Is it safe to put the client-side ID in my website’s JavaScript?
Yes, that is its purpose. Just remember that anything a client can read is visible to users, so never place secrets in flag values and never rely on a client-side flag alone to guard something important.
Q3Can a server-side SDK use the client-side ID?
Some can, but only in remote evaluation mode. Local evaluation needs the secret key, because it downloads the complete rulebook. For production services, use the server-side key.
Q4Can a leaked server-side key change my flags?
No. It is a consumer credential. It exposes your targeting rules and values, but changing flags requires a dashboard login or an administrative credential. It should still be replaced promptly after any exposure.
Q5How many server-side keys can I have?
You can create several per environment, each with its own name. Using one per consumer is strongly recommended, because it makes tracing and revocation precise.
Q6How do I rotate a server-side key without downtime?
Create the new key, store it, roll it out to every consumer, verify nothing uses the old one, and only then delete the old key. At every moment, each service has at least one working key.
Q7What does “unauthorised” versus “forbidden” mean in my logs?
“Unauthorised” means Flagsmith did not recognise the key at all, often a typo or a deleted key. “Forbidden” means the key is real but the wrong type for the action, such as using the client-side ID to fetch the environment document.
Q8Where is the safest place to store a server-side key?
In a managed secrets service, read by the service at start-up using its own platform identity, and held only in memory. Never in source code, container images, chat messages, or documents.
Q9Should developers use production keys on their laptops?
No. Give developers a development environment with its own keys. Production keys belong only to production workloads, where access is controlled and audited.
Q10What if I committed a key to a repository by mistake?
Treat it as leaked. Create a replacement, deploy it, delete the exposed key, and then clean up the repository. Removing the key from the latest version does not remove it from history.
Q11Is the same key used to manage flags through scripts?
No. Environment keys are for reading flags in applications. Scripts that create or edit flags need a separate administrative credential, stored with at least the same care.
Q12Do keys work the same way in a self-hosted Flagsmith?
Yes, the two key types behave the same way. The differences are that you point the SDK at your own address, and you are responsible for protecting the server and database where the keys are stored.

XSummary and Key Takeaways

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

Every Flagsmith environment offers two keys because applications run in two kinds of places. The client-side ID is a public address that lets browsers and apps ask what one identity should see. The server-side key is a secret credential that lets trusted backends read flags and download the whole environment document. Keeping the first public and the second private, storing secrets properly, rotating with overlap, and watching for trouble are the habits that keep feature flags a convenience and not a liability.

Key Takeaways

  • Two keys, two trust levels. The client-side environment ID is public and limited; the server-side environment key is secret and can download the full rulebook for local evaluation.
  • Ask who can read the code. If a stranger can open it, such as a browser, phone app, or shipped program, use only the client-side ID. If it runs privately in your infrastructure, use a server-side key.
  • Public is not harmless. Never put secrets in flag values a client can read, use opaque identifiers, hide disabled flags, and evaluate confidential targeting on your server.
  • A leaked server-side key discloses, but does not control. It exposes your rules and values without allowing flag changes, yet it must be replaced promptly, because it works until someone deletes it.
  • Keep management separate. Environment keys are for consuming flags; dashboard logins and administrative credentials manage them, each with its own lifecycle and storage.
  • Store, name and rotate deliberately. Use one named key per consumer and environment, keep it in a secrets manager, and rotate with overlap: new key first, old key last.
  • Prepare for the bad day. Turn on secret scanning, scan front-end bundles, watch authentication errors by key name, and keep a rehearsed runbook that replaces first and revokes second.