SDK Initialization in Flagsmith

SDK Initialization in Flagsmith

A plain-English guide to the first few seconds of a Flagsmith-powered app: what "initializing" really means, which settings matter, what happens behind the scenes, and how to start up quickly, safely and calmly, even when the network misbehaves.

Picture the moment a customer taps your app icon. Before the first screen appears, your code must decide a dozen things: show the new banner or the old one, enable the beta checkout or hide it, display five items per row or three. Those decisions come from feature flags, and your app can only make them once it has asked Flagsmith for the answers.

The step that connects your app to Flagsmith is called initialization. It happens once, very early, and it quietly sets the rules for everything that follows: how fast screens appear, what users see when the network is slow, how much load you place on Flagsmith, and how safe your secret keys are. A tidy initialization makes the rest of your flag usage almost boring. A careless one causes flickering screens, empty spinners and mysterious bugs that only appear on slow phones.

You do not need to know anything about SDKs, networks or feature flags to follow this guide. Every new word is explained when it first appears, with an everyday comparison. By the end you will understand what initialization does, which settings deserve your attention, how the process unfolds step by step, what can go wrong and how to design your own startup so it stays calm under pressure.

1Starting From Zero: Flags, SDKs and Why Startup Matters

Before initializing anything, let us be sure about what is being initialized.

Feature flags in one minute

A feature flag is a switch in your software that decides whether a feature is visible. Instead of hiding a new button by deleting code, you wrap the button in a check: “if the flag is on, show it.” Later you flip the flag in a dashboard and the button appears or disappears without shipping a new release. A remote config value is a close cousin. Instead of just on or off, it holds a number or some text, such as how many items to show per page.

What an SDK is

An SDK, short for software development kit, is a ready-made code library that makes it easy to use a service. Instead of writing the low-level conversation with Flagsmith yourself, you add the SDK to your project and call friendly functions such as “is this flag enabled?” The SDK handles the sending of requests, the reading of replies, the remembering of results and many small details you would rather not write.

Analogy

Think of a translator at an international meeting. You speak your own language, the other side speaks theirs, and the translator carries meaning back and forth. You never learn the other language. The SDK is that translator between your app and Flagsmith.

What initialization means

Before a translator can work, they must arrive, introduce themselves and learn which meeting they are attending. Initialization is the same for an SDK. You tell it which Flagsmith environment to talk to, how to behave when things go wrong, and what to do with the answers. Many SDKs also fetch the first set of flags during this step so that your code has something to read straight away.

Why the first moments matter most

Flags often decide what the very first screen looks like. If your app draws the screen before the flags arrive, one of two ugly things happens. Either the user sees a blank loading spinner, or the app shows the old version and then abruptly switches to the new one, which feels like a flicker. Both make an app feel unpolished. Good initialization is how you avoid both.

!
Tip

Whenever you meet a new word in this guide, ask three questions: what is it, why does it exist, and what would break without it? Those answers explain most of what you need to know.

2What Initialization Does: The Short Version

Five jobs, done once, early.

Although the details differ between languages, nearly every Flagsmith SDK performs the same handful of jobs when you initialize it. Learning them as a list makes the settings that follow easy to understand, because each setting tunes one of the jobs.

Job one

Identify the environment

You provide a key that tells Flagsmith which environment, such as production or staging, your app belongs to. Everything else depends on it.

Job two

Choose where to talk

The SDK needs the address of the Flagsmith service. The hosted service address is built in. Self-hosters supply their own.

Job three

Set behaviour rules

Timeouts, retries, caching, defaults and update styles are decided here, so that later calls behave consistently.

Job four

Fetch the first flags

Many SDKs ask Flagsmith for the initial set of flags straight away, so the app has real answers early.

Job five

Get ready for questions

The SDK stores what it learned in memory so your code can ask about flags quickly, as many times as it likes, without more network trips.

Optional

Stay up to date

Depending on settings, the SDK may keep refreshing in the background or listen for live updates, so long-running apps stay current.

One copy, shared by everyone

In most apps you should initialize the SDK exactly once and share that single instance across the whole program. Creating a new instance in every screen or function wastes network calls, throws away what was already learned and invites the flicker you are trying to avoid. Think of it as hiring one translator for the whole meeting, not a fresh one for every sentence.

1
initialization per app run, shared everywhere
5
core jobs: environment, address, rules, first fetch, readiness
0
network calls needed to read a flag afterwards, in most designs
!
Watch out

Names of settings and exact behaviour differ between languages and versions. This guide teaches the ideas that stay true everywhere. Always confirm the precise setting names and defaults in the official documentation for the SDK you are using.

3The Big Picture: Where the SDK Fits

One picture holds the whole story.

flowchart LR
  App["Your App Code"] --> SDK["Flagsmith SDK: initialized once"]
  SDK --> Mem["In-Memory Flag Store"]
  SDK -->|"environment key"| Edge["Flagsmith Edge API"]
  Edge --> Data["Replicated Environment Data"]
  Admin["Dashboard or Admin API"] --> Core["Flagsmith Core"]
  Core -->|"publishes changes"| Data
  App -->|"asks: is flag on?"| Mem
Figure 1. The SDK sits between your code and Flagsmith, and keeps answers in memory for quick reading.

Reading the picture

On the left is your own code. It never talks to Flagsmith directly. It talks to the SDK. The SDK holds a small store in memory. When your code asks “is this flag on?”, the SDK looks in that store and answers immediately, with no network trip. Only during initialization, and again whenever the SDK refreshes, does it reach out to the Flagsmith serving layer, using your environment key to say which environment it wants.

On the right is Flagsmith itself. People change flags through the dashboard or the admin interface, which talk to the core. The core saves the changes and publishes updated settings to the serving layer. The next time your SDK asks, it receives the new values. This separation is why reading flags is fast: the SDK talks to a nearby, read-focused service, never to the busy editing system.

The two moments of contact

The SDK is in contact with Flagsmith at two kinds of moments. The first is startup, which is the subject of this guide. The second is refresh, when the SDK updates its stored answers later. Everything you configure during initialization shapes how both moments behave.

Analogy

A traveller arrives in a new city and buys a local guidebook at the airport. That purchase is initialization. For the rest of the trip, they read the guidebook instead of phoning a travel agent for every question. Now and then they buy an updated edition. The guidebook is the SDK’s in-memory store.

MomentWhat happensWho decides how
StartupSDK is configured and fetches the first flagsYour initialization settings
ReadingYour code asks the SDK, which answers from memoryThe SDK, with no network cost
RefreshSDK updates its stored answersTimers, live updates or manual refresh settings
FailureNetwork or service is unavailableYour defaults, cache and timeout settings

4The Most Important Setting: The Environment Key

One short string decides whose flags you get.

Organisations, projects and environments

Flagsmith organises things in layers. An organisation is your company account. A project is usually one product. An environment is one stage of that product, such as development, staging or production. The same flag exists in every environment but can be on in one and off in another. This is how you test a feature safely before real customers see it.

What the key does

Each environment has its own environment key, a string that identifies it. When you initialize the SDK with a key, you are saying “I belong to this environment.” Flagsmith uses the key to find the right flag settings and, together with the type of key, to decide what you are allowed to see.

Two kinds of keys

This is the most important distinction in the whole guide. Flagsmith uses two kinds of environment keys, and they must never be confused.

Public

Client-side key

Designed for code that runs on a user’s device, such as a website or mobile app. Because anyone can look inside such code, this key is treated as public. It can only read flags for its environment.

Secret

Server-side key

Designed for your own backend servers. It is a secret, and it unlocks extra abilities such as downloading the whole environment for local decisions. It must never reach a user’s device.

Analogy

A client-side key is like the address printed on a shop’s window. Anybody walking past can read it, and it only tells them where the shop is. A server-side key is like the key to the stock room. It opens things that customers should never touch, so it lives in the owner’s pocket.

Where to keep keys

Client-side keys can sit in your app’s configuration, because they are designed to be seen. Server-side keys belong in a secrets manager or protected environment settings, and are injected when the server starts. They should never appear in source code repositories, build logs, chat messages or screenshots. If a server-side key is ever exposed, create a new one and retire the old one immediately.

!
Watch out

The most common beginner mistake is placing a secret server-side key in a mobile app or a website. Treat that key like a password. If it leaks into public code, anyone can use it, and they could read your whole environment’s rules.

One key per environment, always

Use a different key for each environment, and make your build or deployment choose the right one automatically. A production app built with the staging key shows staging flags to real customers. A staging build with the production key makes your tests flip real settings. Name keys clearly in your own secrets store, such as “web-client-production,” so nobody grabs the wrong one.

5Client-Side and Server-Side SDKs

Two families of SDK, two different jobs, two different initialization styles.

Client-side SDKs

Client-side SDKs run in places users control: web browsers, phones, tablets and desktop apps. They usually serve one user at a time. They initialize with the public environment key, often together with the identity of the current user, and they ask Flagsmith “what are the flags for this person?” The answers are kept in memory, and sometimes saved to local storage so the next app launch can start instantly.

Server-side SDKs

Server-side SDKs run in your own backend: web servers, workers, scheduled jobs. A single server handles thousands of different users, so it asks about many identities. These SDKs initialize with the secret key. They can work in two ways. In remote evaluation, the server asks Flagsmith for each user’s flags. In local evaluation, the server downloads the whole environment’s rules once, keeps them in memory, and decides for each user on its own machine, refreshing the rules on a timer.

QuestionClient-side SDKServer-side SDK
Runs whereBrowser, phone, desktop appYour own backend servers
Key typePublic client-side keySecret server-side key
Users servedUsually oneMany, one request at a time
Typical styleFetch this user’s flags, keep in memoryRemote evaluation or local evaluation
Main startup concernShow the right screen quicklyBe ready before taking traffic
Biggest riskFlicker and slow first paintLeaked secret key
Analogy

A client-side SDK is like a personal assistant who works for one executive and keeps that person’s schedule in a notebook. A server-side SDK is like a receptionist at a busy office who serves a stream of visitors and may keep a copy of the whole company handbook on the desk to answer quickly without phoning anyone.

Why this split shapes initialization

The two families have different priorities. On a phone, the priority is to draw a correct first screen fast, even on a poor connection. On a server, the priority is to be fully ready before accepting traffic, because answering with missing data would affect many users at once. The rest of this guide returns to this difference again and again.

!
Tip

If you are not sure which family you need, ask where the code runs. If a stranger could open it, it is client-side. If only your own staff can reach it, it is server-side.

6Internal Working: The Life of One Startup

Follow the SDK from the moment your app launches until it is ready.

sequenceDiagram
  participant A as Your App
  participant S as Flagsmith SDK
  participant L as Local Cache
  participant F as Flagsmith Serving Layer
  A->>S: Initialize with key and settings
  S->>S: Validate settings and prepare memory store
  S->>L: Check for saved flags from last run
  L-->>S: Return saved flags if present
  S->>F: Request current flags with key
  F-->>S: Return flags and values
  S->>S: Store in memory and update cache
  S-->>A: Signal ready
  A->>S: Is feature enabled?
  S-->>A: Answer from memory
Figure 2. During startup the SDK validates its settings, may reuse saved flags, fetches fresh ones, and then signals readiness.

Step by step

1

Your app calls initialize

You pass the environment key and any settings. Nothing has touched the network yet.

2

The SDK checks its settings

It confirms a key was supplied, applies defaults for anything left out, and prepares an empty store in memory.

3

It may load saved flags

If caching is enabled, the SDK reads flags saved from the previous run. These are instantly available, though possibly a little old.

4

It asks Flagsmith for fresh flags

The SDK sends a request with the key, and the identity if one is known. The serving layer evaluates the rules and replies.

5

It stores the answer

The reply is placed in memory and, if caching is on, saved for the next launch.

6

It signals readiness

Initialization finishes. In many SDKs this is an awaited step or a callback, and your code should wait for it before reading flags that affect the first screen.

7

Your code reads flags from memory

From now on, each question is answered instantly from the stored copy, with no network cost.

What if step four fails?

Networks are not perfect. If the request fails or times out, a well-configured SDK does not crash your app. It uses what it has: saved flags from a previous run if they exist, and otherwise the default values you provided. This is why the next chapters spend so much time on defaults and caching. They are what turns a failure into a quiet non-event.

Analogy

A pilot preparing for take-off runs a checklist: check the instruments, load the flight plan, request clearance. If the radio fails at the last item, the pilot does not abandon the airport. There is a printed backup plan in the cockpit. Defaults and caches are your SDK’s printed backup plan.

7Choosing the Service Address

Which Flagsmith should the SDK talk to?

The hosted service

If you use Flagsmith’s hosted cloud service, SDKs come with the right address built in, pointing at the globally distributed serving layer. In that case you normally leave the address setting alone. Providing only the environment key is usually enough to start. This is by design: the fewer settings you must get right, the fewer you can get wrong.

Self-hosted and private installations

Some organisations run Flagsmith on their own servers, because of company rules, legal requirements or a wish for full control. In that case you must tell the SDK where your installation lives by providing its address. The address should use the secure form, so the conversation is encrypted. A mistyped address is one of the most common reasons for a first test failing, so copy it carefully, including any version portion at the end that your documentation specifies.

The edge proxy

Self-hosting teams often add an edge proxy near their apps. This is a small component that holds a cached copy of environment data and answers SDK requests itself, asking the main installation only now and then for updates. In that arrangement, your SDK points at the proxy’s address instead of the main server. The benefits are lower delay and less load on your main installation.

Your setupAddress settingWhy
Flagsmith hosted cloudLeave as defaultBuilt in and points to the distributed serving layer
Self-hosted, directYour installation’s secure addressSDK must know where your server lives
Self-hosted with edge proxyThe proxy’s addressFaster local answers, less load on the main server
Testing against a local copyLocal address, development keySafe experiments without touching shared environments
Analogy

A delivery driver needs the correct street address. For a big chain store, the address is on the company website. For a private home, you must be told it. Pointing an SDK at a self-hosted service is giving the driver the private address.

!
Watch out

Never switch to an unencrypted address “to make debugging easier.” Always use the secure form, and keep your environment keys and user identities from travelling across the network in the clear.

8Default Values: Your Safety Net

The most valuable setting you will ever choose is the one used when everything goes wrong.

What a default is

A default value is the answer your code uses when the SDK cannot get a real one. Maybe the phone has no signal. Maybe the service is briefly unreachable. Maybe the flag was deleted. In all these cases, your code needs to know what to do, and the default tells it.

Where defaults live

Most SDKs let you provide defaults at initialization time, through a handler or a list of fallback flag values. Some also let you pass a default each time you ask about a flag. Setting them in one place at startup is neater, because every part of the app then shares the same fallback behaviour.

Choosing good defaults

The rule is simple: the default should be the safe, stable, well-tested behaviour. For a brand-new feature that means “off.” If the network fails, users see the version of the app they already know, not an unfinished feature. For a kill switch that normally guards something risky, the safe default depends on the situation, so decide deliberately rather than by habit.

Good default thinking

  • New, untested features default to off.
  • Config values default to the long-standing, known setting.
  • Defaults are decided with the product team, not guessed.
  • The app is tested with the network switched off.

Risky default thinking

  • Defaulting a half-built feature to on “so we can see it.”
  • Leaving defaults unset and hoping an error never happens.
  • Different defaults in different screens for the same flag.
  • Never testing what happens when the answer is missing.
Analogy

Every building has an emergency lighting circuit that switches on when the main power fails. It is not as bright as normal lighting, but it keeps people safe and able to find the door. A good default is the emergency lighting of your app: modest, reliable and always ready.

!
Tip

Keep your default flags in one small file that is reviewed like any other code. When someone adds a new flag, adding its default becomes part of the same change.

9Timeouts and Retries

How long to wait, and how often to try again.

Why timeouts matter

A request can fail loudly, with an error. It can also fail silently, by never coming back. Without a time limit, your app could wait forever for a reply that is not coming, leaving the user staring at a spinner. A timeout is the maximum time you are willing to wait. When it passes, the SDK gives up on that attempt and moves on to its fallback behaviour.

Choosing a sensible value

A timeout that is too short causes false alarms on slow networks, so users on poor connections always get fallbacks. A timeout that is too long causes long waits. For flags that gate the first screen, aim to keep the wait short, in the range of a second or two, and rely on cache and defaults beyond that. For background refreshes that nobody is waiting on, a longer limit is fine.

Retries and backoff

Some failures are temporary: a brief network blip or a busy server. Trying again often works. But retrying instantly and endlessly makes a struggling service worse. The polite approach is called backoff: wait a short time before the first retry, longer before the second, longer again before the third, and stop after a few attempts. Many SDKs let you set the number of retries. Keep the number small.

flowchart TD
  S["Need flags at startup"] --> C{"Cached flags available?"}
  C -->|"Yes"| U["Use cached flags immediately"]
  C -->|"No"| N["Call Flagsmith with timeout"]
  U --> N
  N --> OK{"Reply received in time?"}
  OK -->|"Yes"| V["Store fresh flags and cache them"]
  OK -->|"No"| R{"Retries left?"}
  R -->|"Yes"| W["Wait, then try again"]
  W --> N
  R -->|"No"| D["Keep cached flags or fall back to defaults"]
Figure 3. A careful startup uses the cache, asks with a time limit, retries a few times politely, and falls back safely.
Analogy

If you phone a friend and nobody answers, you do not redial fifty times in a row. You wait a bit, try again, wait longer, and perhaps send a message instead. Backoff is the polite way of redialing.

!
Watch out

Never let a flag call block your whole screen with no time limit. A user on a slow train would rather see the familiar version of your app now than a perfect version never.

10Caching: Remembering Between Launches

The fastest answer is the one you already have.

Two kinds of memory

An SDK can remember flags in two ways. The first is in-memory storage, which lasts only while the app is running. When the app closes, it is gone. The second is persistent storage, which saves flags to the device or disk so they survive a restart. Persistent caching is mostly useful for client-side apps, which are opened and closed all the time.

What caching gives you

  • Instant first screens. The app can draw the right screen straight away from saved flags, then update quietly if fresh flags differ.
  • Resilience. If the network is down at startup, the app still has real values from the last successful run, which is far better than bare defaults.
  • Fewer requests. Repeated quick launches need fewer network trips, which saves battery, data and cost.

The freshness trade-off

Cached flags can be out of date. If a product manager switched a feature off ten minutes ago, a user opening the app from cache may briefly still see it. Many SDKs let you set a time to live, the maximum age of cached flags before they are considered too old. A short lifetime means fresher flags and more requests. A long lifetime means fewer requests and a longer wait before changes reach users. Choose according to what a stale flag would cost you.

Cache lifetimeBenefitCostSuits
Very short (seconds)Almost always freshMany requests, little savingRare, mostly debugging
Short (minutes)Fresh enough, saves requestsBrief stalenessMost interactive apps
Long (hours)Very few requests, strong offline startChanges take time to arriveDecorative features, low-risk flags
Not usedAlways the latestSlow starts, weak offline behaviourServer-side designs with local evaluation
Analogy

A milk carton has a use-by date. Fresh milk tastes best, but nobody checks the dairy every morning. You keep a carton in the fridge, glance at the date, and replace it when it gets old. Cache lifetime is the use-by date on your flags.

Showing cached flags and then updating

A popular approach is to draw the first screen from cached flags immediately, fetch fresh flags in the background, and update the screen only if something changed. This gives the speed of a cache and the accuracy of a fresh fetch. Take care with the update step. Switching major layouts under the user’s finger feels jarring, so many teams apply fresh values at the next natural moment, such as the next screen or the next launch, unless the change is urgent.

!
Tip

Ask which flags truly must change instantly, and which can wait until the next launch. Most decorative or experimental flags can wait, which keeps screens stable and users calm.

11Identity and Traits at Startup

Telling Flagsmith who is using the app.

Why identity matters

Without knowing who the user is, Flagsmith can only give general answers that are the same for everyone. When you provide an identity, which is a stable ID for one user, Flagsmith can give personalised answers: flags that depend on the user’s group, plan or country, and consistent results in percentage rollouts.

Traits

A trait is a small fact about an identity, such as “plan equals premium” or “app version equals 5.2.” A segment is a group of users defined by rules over traits, such as “all premium users in India.” When you send traits during initialization, Flagsmith can place the user in the right segments straight away and evaluate flags accordingly.

Anonymous users

Not every visitor is signed in. For anonymous visitors, you have two choices. You can ask for the general flags that need no identity. Or you can create a temporary, random identifier, store it on the device, and reuse it on later visits, so that the person receives consistent results over time. A fresh random ID on every visit means the person drifts between rollout groups, seeing a feature one day and not the next.

When the user signs in or out

Identity can change while the app runs. A guest signs in. A user switches accounts. In those moments your code should tell the SDK about the new identity so flags are re-evaluated. Treat sign-out similarly, so that the next person on a shared device does not inherit the previous person’s flags or traits.

Analogy

A hotel gives a guest a key card coded for their room. If a different guest checks in, the card is recoded. Using an old card for a new guest would open the wrong door. Telling the SDK about a new identity is recoding the key card.

Good practice

Stable internal IDs

Use an internal user number rather than an email address, so identities stay stable and no personal data travels.

Good practice

Few, small traits

Send only the facts you will actually use in rules, such as plan, region and app version.

Careful

Sensitive facts

Avoid putting health, financial or other sensitive details in traits. Everything sent is stored by a third party.

Careful

Changing IDs

An ID that changes each session breaks rollouts and any personal overrides you have set.

!
Watch out

Traits are stored in Flagsmith, and may be held in several regions. Review your privacy rules before deciding what to send, and follow the principle of sending only what you need.

12Waiting for Readiness Without Freezing the App

Initialization takes time. How should the rest of the app behave while it happens?

Asynchronous start

Fetching flags takes a network trip, so initialization is usually asynchronous. That means your code starts the process, carries on, and is told later when it is complete. Different languages offer different ways to express this: an awaited call, a callback or a promise. All of them express the same idea: “start now, tell me when it is done.”

Three strategies for the first screen

Strategy A

Wait briefly, then continue

Hold the first screen for a short, fixed time. If flags arrive, use them. If not, continue with cache or defaults. Good when the first screen depends heavily on flags.

Strategy B

Draw now, update later

Draw the screen at once from cache or defaults, then update when fresh flags arrive. Fast, but may cause visible changes.

Strategy C

Splash while loading

Show a branded loading screen for a short, bounded time while the SDK prepares. Familiar and tidy, but only if the wait is short.

Choosing between them

Ask how much the first screen depends on flags. If a flag decides the entire layout, Strategy A or C protects users from flicker. If flags only tweak small details, Strategy B keeps the app snappy. A common blend is to wait up to a second or so for fresh flags, then proceed with whatever is available, and apply late arrivals only at safe moments.

flowchart TD
  L["App launches"] --> I["Start SDK initialization"]
  I --> T{"Ready within the wait budget?"}
  T -->|"Yes"| F["Draw first screen with fresh flags"]
  T -->|"No"| C["Draw first screen with cache or defaults"]
  C --> B["Initialization finishes in background"]
  B --> U{"Flags changed?"}
  U -->|"Yes, urgent"| A["Apply now"]
  U -->|"Yes, not urgent"| N["Apply at next screen or launch"]
  U -->|"No"| D["Nothing to do"]
Figure 4. A bounded wait keeps the app responsive, and late flags are applied only when it is safe.
Analogy

A restaurant host tells a family, “Your table will be ready in about five minutes.” If it is ready sooner, wonderful. If it is not, the host does not make them wait outside forever. They are shown to a temporary seat and moved when the table is free. A bounded wait is that host.

!
Tip

Measure how long real users wait for initialization, especially at the slow end. A timeout chosen from real data beats one chosen from a hunch.

13Local Evaluation on the Server

Server-side SDKs have an extra trick that changes how initialization works.

What local evaluation is

In ordinary remote evaluation, a server asks Flagsmith each time it needs a user’s flags. In local evaluation, the server downloads the full set of environment rules once, stores them in memory and makes decisions entirely on its own machine. No network trip is needed to answer each question, which makes decisions extremely fast and greatly reduces requests.

What changes at initialization

To use local evaluation, you enable it in the SDK settings and provide the secret server-side key, which is required to download the full environment. During startup, the SDK fetches the environment document, which is a compact bundle holding all flags, segments and rules. Until that first download completes, the SDK cannot decide locally, so a well-designed server waits for it before accepting traffic or falls back to a safe behaviour.

Refreshing the rules

Rules change over time, so the SDK refreshes its copy on a timer. A shorter interval means changes arrive sooner and more requests are made. A longer interval means fewer requests and a longer wait for changes. Typical intervals are measured in tens of seconds. If a refresh fails, the SDK keeps using its last good copy, so a brief outage of the Flagsmith service does not stop your decisions.

QuestionRemote evaluationLocal evaluation
Where decisions happenAt Flagsmith’s serving layerInside your server process
Network per decisionUsually one request per user lookupNone after the first download
FreshnessVery fresh, after a short publish delayAs fresh as the refresh interval
Key neededServer-side or client-side key as appropriateServer-side secret key
Best forSimple setups, small trafficHigh-volume trusted backends
Analogy

A receptionist who phones head office to check the rules for every visitor is slow but always up to date. A receptionist who keeps a copy of the handbook on the desk is quick, and replaces the handbook whenever head office sends a new edition. Local evaluation is the handbook on the desk.

!
Watch out

Local evaluation needs the secret key, so it is only for trusted backends. Never enable it in code that runs on a user’s device, and check your SDK’s documentation for any listed differences between local and remote results.

14Staying Up to Date: Polling and Live Updates

Initialization starts the story. Updates keep it current.

Why updates matter

A web page may stay open for hours. A server may run for weeks. During that time, product managers change flags. Without some way of updating, your app would keep using the answers it learned at startup, which grow stale. Initialization is where you choose how updates will arrive.

Three update styles

Style one

No automatic updates

The app learns flags at startup and again at the next launch. Simple and cheap, but changes appear slowly.

Style two

Polling on a timer

The SDK asks again every so often, such as every minute or five minutes. Predictable, but wastes some requests when nothing changed.

Style three

Live updates

Some SDKs can keep a lightweight connection open so Flagsmith announces changes as they happen. Fast and efficient for long-lived pages, where supported.

How live updates work, simply

Live updates commonly rely on a standard technique where the server pushes small messages down a connection that stays open, so the page does not need to keep asking. When a flag changes, the message arrives within moments and the SDK refreshes. This suits web apps that stay open all day. Availability and settings differ between SDKs, so check your documentation.

Responding to a change

SDKs usually let you register a function that is called whenever flags change. Use it with care. Updating the screen the instant a flag flips can surprise users, especially if it rearranges what they are looking at. Decide, flag by flag, whether an update should show immediately or wait for a natural moment.

flowchart LR
  P["Product Manager changes a flag"] --> C["Flagsmith saves and publishes it"]
  C --> D{"How does the SDK learn?"}
  D -->|"Timer"| T["Next scheduled refresh asks again"]
  D -->|"Live connection"| L["Flagsmith announces the change"]
  D -->|"Neither"| N["Learned at next app launch"]
  T --> S["SDK updates its stored flags"]
  L --> S
  N --> S
  S --> H["Change handler decides when to apply it"]
Figure 5. A change can reach the SDK by timer, by live announcement or at the next launch, and the handler decides when to apply it.
Analogy

There are three ways to hear the news. You can check the paper once a morning, you can look at your phone every few minutes, or you can have an alert that rings when something important happens. Choose the one that matches how soon you truly need to know.

15Offline Mode and Working Without the Network

Sometimes there is no Flagsmith to talk to, and that can be on purpose.

Why anyone would go offline deliberately

Some environments cannot or should not reach the internet: secure internal networks, aircraft systems, test pipelines that must be repeatable, or apps that must start in a basement with no signal. Many SDKs offer an offline mode in which they never call Flagsmith and instead read flag data from a source you supply, such as a file prepared earlier.

How it works in outline

Flagsmith can export the data of an environment into a file. You package that file with your app or place it where the server can read it. At initialization you switch the SDK into offline mode and point it at the data. The SDK then evaluates flags using that data, with no network at all. To change flags, you export a new file and deploy it.

Offline handlers and fallbacks

Some SDKs also support using offline data as a fallback while normally running online: if the live service is unreachable at startup, the SDK uses the packaged data instead of bare defaults. This is a stronger safety net than defaults alone, because the packaged data reflects real rules, not just a single fixed answer per flag.

Advantages

  • Works with no network at all.
  • Repeatable results, ideal for automated tests.
  • No outbound traffic, helpful in locked-down environments.
  • Strong startup safety net when used as a fallback.

Trade-offs

  • Flags change only when you ship a new data file.
  • The file can grow stale if nobody refreshes it.
  • Extra step in your build or deployment process.
  • Personal overrides on the live service are not seen.
Analogy

A hiker carries a printed map in case the phone has no signal. The map may be a little behind the satellite view, but it gets the hiker home. Offline data is the printed map of your flags.

!
Tip

Use offline mode in automated tests. A test that depends on a live service can fail for reasons unrelated to your code. A test that reads a fixed file gives the same answer every time.

16Analytics and Usage Reporting

An optional setting that tells Flagsmith which flags you actually use.

What it is

Many SDKs can report how often each flag is evaluated. Flagsmith uses the reports to show usage in its dashboard, which helps you see which flags are alive and which are dead. Knowing a flag has not been read by any app for three months is valuable evidence when deciding whether to delete it.

Initialization choices

You usually enable or disable this reporting when you initialize. If enabled, the SDK collects counts in memory and sends them in batches at an interval you can set, instead of making a request for every single evaluation. Batching keeps the overhead small. If you do not need the information, you can leave it off.

Do not confuse two kinds of analytics

This flag usage reporting is a feature inside Flagsmith, and it is separate from third-party analytics integrations that send flag states to tools such as product analytics platforms. The first answers “which flags are being read?” The second answers “which users saw which version, and what did they do?” You can use both.

SettingEffectConsider
Usage reporting onDashboard shows which flags are readSmall extra traffic in batches
Usage reporting offNo usage data collectedFewer requests, less insight for cleanup
Short reporting intervalFresher usage numbersMore frequent batches
Long reporting intervalFewer batchesNumbers lag, and data may be lost if the app closes first
Analogy

A library counts how often each book is borrowed. The counts help the librarian decide which books to keep on the front shelf and which to move to storage. Flag usage reporting is the borrowing record for your flags.

17Setting Up Step by Step

A calm, ordered path from nothing to a working initialization.

1

Create the environments

In the dashboard, make development, staging and production environments, each with its own key.

2

Pick the right SDK

Choose the SDK for your language and decide whether you need a client-side or server-side one.

3

Store the key properly

Put client-side keys in app configuration. Put server-side keys in a secrets manager.

4

Write one initialization routine

Create a single function or module that initializes the SDK once and exposes the shared instance to the rest of the app.

5

Provide defaults and limits

Add safe default flags, a timeout, a small retry count and, for clients, caching.

6

Decide the first-screen strategy

Choose how long to wait for flags, and what the app shows if they are late.

7

Test in development

Flip a flag in the dashboard, wait a few seconds, and confirm the app changes. Repeat in staging before production.

8

Add monitoring

Track initialization time, failures and how often defaults are used, and set alerts before launch.

A checklist of settings to review

Required

Environment key

The right key for the right environment and the right SDK family.

Usually default

Service address

Leave alone for the hosted service. Set carefully for self-hosting or a proxy.

Strongly advised

Default flags

Safe fallbacks for every flag your code reads.

Strongly advised

Timeout and retries

A bounded wait and a small, polite number of retries.

Client apps

Caching

Saved flags for instant starts and offline resilience.

Server apps

Local evaluation and refresh interval

For high-volume backends, with a sensible refresh timer.

Optional

Usage reporting

Helpful for cleanup, at the cost of small batched traffic.

Optional

Live updates and change handler

For long-lived pages that need fast change delivery.

!
Tip

Keep the initialization code in one small, well-named module. When something about startup needs to change, there is exactly one place to look.

18Security and Privacy at Startup

The first call sets the tone for everything that follows.

Keys again, because they matter most

Use the public client-side key in apps and the secret server-side key only on servers. Keep secrets out of source control and build logs. Scan your repositories for accidentally committed keys. Rotate server-side keys on a schedule and immediately when a person who knew them leaves.

Encryption in transit

Initialization requests travel over HTTPS, which scrambles the conversation so anyone listening on the network sees only noise. Never use an unencrypted address, even in development, because habits formed in development tend to follow code into production.

What leaves the device

When you send an identity and its traits during initialization, you are sending information about your users to a third party and storing it there. Follow data minimisation: send only what rules need. Prefer internal IDs over emails and coarse facts like a plan name over detailed personal ones. If strict rules such as the European Union’s GDPR apply to your users, check where the data is stored and whether regional options are available.

Cached data on devices

Saved flags and traits on a device are stored in the app’s local storage. Treat them as readable by the device owner. Do not cache anything you would not want shown on a screen. On shared devices, clear cached identity data on sign-out.

RiskExampleSimple defence
Secret key in an appServer key shipped inside a mobile buildUse only client-side keys on devices
Wrong environmentProduction build using the staging keyAutomatic key selection per build, tested before release
Over-sharingEmails and names sent as traitsUse internal IDs and coarse traits
Unencrypted trafficPlain address in a test buildSecure addresses everywhere
Leftover identityPrevious user’s cached flags on a shared deviceClear cache and identity on sign-out
Analogy

When you hand a parcel to a courier, you decide what goes inside. Once sealed and collected, it cannot be pulled back. Anything sent to an outside service at startup works the same way, so decide first what truly belongs in the parcel.

19Performance and Scalability

Startup is the busiest moment of an app’s life, so it deserves care.

Why startup is expensive

At launch, an app is doing many things at once: loading code, drawing screens, reading storage and talking to several services. Adding a slow flag request to that crowd can noticeably delay the first useful screen. A careful initialization keeps its own footprint small.

Habits that keep it light

  • Initialize once. A second initialization repeats the network trip and discards what was learned.
  • Request all flags at once. One request that returns every flag is cheaper than many requests for single flags.
  • Start early, read late. Begin initialization as early as possible and read flags only when needed, so the network trip overlaps with other startup work.
  • Use the cache. Drawing from saved flags removes the network from the critical path.
  • Keep the key lookup cheap. Avoid slow work, such as reading remote configuration, just to find the key.

The thundering herd

Imagine a marketing email sends a million people to your app within minutes, and every app instance initializes at once. That sudden crowd is called a thundering herd. Flagsmith’s serving layer is built to absorb such spikes, but your own servers must cope too. For server fleets, stagger restarts so every instance does not download the environment at the same instant, and add small random delays to refresh timers so instances do not all refresh together.

1
request can fetch every flag at once, instead of one per flag
~1-2 s
a reasonable wait budget for flags that gate the first screen
0
network calls needed for each later flag read from memory
Analogy

When a concert ends, a thousand people reach for the exit at once, and the doors jam. A venue that opens several exits and staggers departures empties smoothly. Staggering server restarts and refresh timers is opening several exits.

!
Tip

Measure the time between app launch and the first useful screen with and without flags. If initialization adds more than a barely noticeable delay, revisit your wait budget and caching.

20Monitoring, Logging and Metrics

If you cannot see how startup behaves on real devices, you are guessing.

Three kinds of signals

Metrics are numbers over time. Logs are text records of events. Traces follow one action through several steps. Together they are called observability, and they let you answer questions about your app without guessing.

What to measure about initialization

Speed

Initialization duration

How long from the start call to readiness, with attention to the slowest one percent, split by region and network type.

Health

Failure rate

The share of startups where the fetch failed or timed out. A rise is an early warning for the network, the service or your own settings.

Fallback

Default and cache usage

How often the app started from defaults or saved flags. A healthy app rarely needs bare defaults.

Freshness

Age of flags in use

How old the flags were that the app actually used, to check your cache lifetime choices.

Volume

Requests per launch

Should usually be one. More means repeated initialization or runaway refreshes.

Change

Update delivery delay

The gap between saving a change in the dashboard and seeing it in a test app.

Logging that explains itself

Many SDKs offer an option to turn on more detailed logging. Enable it in development and in test builds, and keep it quieter in production. A good log line says which environment, whether the cache was used, how long the fetch took, and what the SDK decided. “Flags failed” tells a stranger nothing. “Fetch for production timed out after two seconds, using saved flags aged forty minutes” tells them everything.

Connect flag changes to graphs

A strong habit is placing markers on your dashboards whenever a flag changes, using Flagsmith’s integrations with monitoring tools. When a startup metric jumps, a marker beside the jump shows whether a flag change was involved.

Set a target

Write down what good means, such as “ninety-nine percent of launches are ready within two seconds, and fewer than one in a thousand starts from bare defaults.” A target turns vague feelings into something you can measure and discuss. Such targets are often called service level objectives.

!
Tip

Record the SDK version in your logs and metrics. When a problem appears after an upgrade, being able to filter by version saves hours.

21Design Patterns and Anti-Patterns

Habits that make startup calm, and habits that make it painful.

Patterns worth copying

Pattern

Single shared instance

Initialize once in one module and hand the instance to everything else.

Pattern

Safe defaults file

One reviewed list of fallback values, updated whenever a flag is added.

Pattern

Bounded wait

The first screen waits a short, fixed time for flags and then continues with what it has.

Pattern

Cache then refresh

Draw from saved flags immediately, fetch fresh ones in the background, apply at a safe moment.

Pattern

Ready gate on servers

A server reports itself ready for traffic only after local evaluation data has loaded.

Pattern

Wrapper around the SDK

Your own small interface hides the SDK, so swapping or upgrading it touches one file.

Advantages and trade-offs of a careful startup

Advantages

  • Fast, steady first screens without flicker.
  • Graceful behaviour on poor networks.
  • Fewer requests, lower cost and less battery use.
  • Easy to test and reason about.
  • Changes to flag handling touch a single place.

Trade-offs

  • More settings to choose and document.
  • Cached flags can be briefly stale.
  • A bounded wait sometimes shows defaults to a user.
  • Extra code for readiness and fallbacks.
  • Defaults must be maintained alongside the flags.

Anti-patterns to avoid

ANTI-PATTERN 01Avoid
What people do

They initialize the SDK again in every screen, component or request handler.

Why it hurts

Each initialization repeats the network trip, discards stored flags and can cause flicker. Request counts balloon and costs rise.

Better approach

Initialize once at startup and share the single instance everywhere.

ANTI-PATTERN 02Avoid
What people do

They read flags before initialization has finished and treat the empty answers as real.

Why it hurts

Features that should be on appear off, or the reverse, and the bug seems random because it depends on network speed.

Better approach

Wait for readiness, or deliberately use defaults and handle late updates properly.

ANTI-PATTERN 03Avoid
What people do

They block the entire app on flag loading with no time limit.

Why it hurts

On a bad connection the app appears frozen. Users leave before the first screen ever appears.

Better approach

Set a timeout, use cache and defaults, and let the app continue.

ANTI-PATTERN 04Avoid
What people do

They place the server-side key in a mobile app because it “just works.”

Why it hurts

Anyone can extract the key from the app and read the environment’s full rules.

Better approach

Ship only the client-side key in apps, and keep secrets on servers.

22Best Practices and Common Mistakes

A practical checklist drawn from everything so far.

Do these

  • Initialize exactly once and share the instance.
  • Use the right key in the right place: client-side keys in apps, server-side keys on servers only.
  • Provide safe defaults for every flag, and test with the network switched off.
  • Set a timeout and a small retry count so nothing waits forever.
  • Cache on clients so the next launch starts instantly.
  • Use stable, non-personal identities and small, non-sensitive traits.
  • Wait for readiness on servers before taking traffic when using local evaluation.
  • Monitor initialization time and fallback usage on real devices.

Common mistakes and quick cures

MistakeWhat you seeCure
Wrong environment keyFlags from staging appear in production, or nothing matches the dashboardSelect keys automatically per build and print the environment name in logs
Reading flags too earlyFeatures randomly missing on slow networksWait for readiness or handle late arrival deliberately
No defaultsBlank screens or crashes when the network failsProvide safe defaults for every flag
Fresh anonymous ID every launchUsers flip between old and new versionsStore and reuse a stable ID
Cache never expiresOld flags linger long after changesSet a sensible time to live
Refresh interval too shortHuge request counts and rate limitsLengthen the interval or use live updates
Server key on a deviceSecret exposed in public codeRotate the key and use the client-side key instead
A good initialization is boring: one setup, safe fallbacks, a short wait, and no surprises when the network misbehaves.

23Troubleshooting Guide

When startup misbehaves, check in a calm and predictable order.

The usual suspects

Symptom

All flags are off or at defaults

The fetch is probably failing. Check the key, the address, the network and the logs. Confirm the flags exist in the environment that the key belongs to.

Symptom

Unauthorised errors

The key is missing, mistyped, revoked, or of the wrong type for this SDK. Re-copy it from the dashboard.

Symptom

Flags differ from the dashboard

Wait a few seconds for publishing, check you edited the same environment, and look for cached copies or a long refresh interval.

Symptom

Flicker after launch

The app drew defaults, then received real flags. Wait briefly for flags, or apply late updates at a safe moment.

Symptom

One user sees different flags

Look for an identity override or a segment rule that matches only that user, and check the traits being sent.

Symptom

Browser console shows a cross-origin error

A gateway or proxy in front of the service is not allowing your website address. Update its allowed origins.

A calm order of checks

First, confirm the environment key belongs to the environment you are looking at in the dashboard. Second, confirm the key type matches the SDK family. Third, confirm the service address, especially for self-hosted setups. Fourth, turn on detailed SDK logging and read what the SDK says. Fifth, check that the identity and traits are what you expect. Sixth, look at the status page and your own network. Going through this order avoids blaming the service for a mistake in your settings.

Test with a clean slate

When results are confusing, try a brand new test identity that has never been used, with only the traits you choose. If a clean identity behaves correctly, the problem is likely an old override or stored trait on the other identity. If a clean identity also behaves wrongly, the problem lies in the environment settings or the key.

Self-hosted extras

With a self-hosted installation, additional causes appear: expired certificates, a gateway stripping headers, a stopped background worker so changes never publish, or a firewall blocking outgoing connections. When everything seems right but changes never reach the app, suspect the background worker first.

Analogy

When a lamp does not light, you check the bulb, the switch, the plug and the fuse in that order, not the power station. Troubleshooting startup follows the same short path outward from your own settings.

!
Tip

Keep a development environment and a test identity with a clearly fake ID, such as test-user-001. They give you a safe, repeatable way to check behaviour without touching real customers.

24Testing and Rehearsing Your Startup

A fallback you have never tried is only a hope.

Why test the unhappy paths

Most people test that flags load when everything is fine. The real value lies in testing what happens when things are not fine: the network drops, the answer is slow, the key is wrong, or the service returns an error. Those are exactly the situations in which your defaults, timeouts and caches are supposed to save you.

1

Happy path

Flip a flag in a test environment and confirm the app changes within a few seconds. Note how long it takes.

2

No network at first launch

Install the app fresh, switch the network off, and start it. Confirm it opens with defaults and shows no scary errors.

3

No network at second launch

Run once online, switch the network off, and start again. Confirm the app uses saved flags rather than bare defaults.

4

Slow network

Use a throttling tool to make the connection very slow. Confirm the timeout works and the first screen appears within your wait budget.

5

Wrong key

Use a deliberately wrong key in a test build. Confirm the app falls back cleanly and the logs make the cause obvious.

6

Recovery

Restore the network and confirm the app picks up fresh flags without a restart.

Test the sign-in and sign-out moments

Create fake identities with different traits, such as a premium user, a free user and a user from another country. Sign in as each, check the flags, then sign out and confirm the next identity does not inherit anything. These small tests catch stale identity bugs that are otherwise very hard to reproduce.

Automate what you can

Add a test to your build process that starts the app with offline data and checks the main screens. A second test can use a test environment with a known set of flags. Automated checks catch accidents early, such as a developer removing a default or renaming a flag without noticing.

!
Watch out

Never rehearse failures against real customers. Use separate test environments and test identities, and tell the team in advance so nobody mistakes a drill for a real incident.

25A Worked Example: A Ride-Booking App Gets Its Startup Right

A made-up company shows how the pieces fit together.

The story below is hypothetical. Imagine a ride-booking company called Swift Route, with a mobile app, a website and a pricing service on its servers. The team wants to launch a new “shared rides” option safely and make sure the app opens quickly even in tunnels and lifts.

Step one: separate keys

The team creates development, staging and production environments. The mobile app and website receive the client-side keys. The pricing service receives the server-side key from a secrets manager. The build system picks the right key automatically for each release.

Step two: one initialization module

In each app, a single module initializes the SDK at launch and exposes the shared instance. No screen creates its own. A shared file lists safe defaults: “shared_rides” off, “max_pickup_suggestions” at three.

Step three: a bounded wait

The mobile app waits up to one and a half seconds for fresh flags during the splash screen. If they have not arrived, it continues with saved flags from the last run, or defaults on a first launch. Late flags are applied at the next screen change.

Step four: identity and traits

After sign-in, the app tells the SDK the rider’s internal ID and two traits: city and app version. Guests get a stored random ID so their experience stays consistent between visits. On sign-out, saved identity data is cleared.

Step five: local evaluation on the pricing service

The pricing service uses local evaluation, so it can decide flags for thousands of riders per second without network trips. Each instance reports itself ready for traffic only after its first download completes. Refresh timers include a small random offset so instances do not refresh together.

Step six: gradual launch

“shared_rides” is enabled for staff, then five percent of riders in one city, then wider. A change marker on the dashboards shows each step, and the team watches startup times and error rates alongside.

Step seven: a tunnel and an outage

A rider opens the app in a tunnel. The fetch times out, the app continues with saved flags, and the rider books without noticing anything. Later, a brief Flagsmith network problem affects one region. Backend instances keep their last good copy of the rules and carry on. A small rise in fallback usage appears on a dashboard and then fades.

Step eight: full release and cleanup

The feature is released to everyone. The team removes the flag and the old code path, then removes its default from the defaults file and closes the ticket.

What made this smooth

Nothing needed heroics. The team used separate keys for safety, one shared initialization for efficiency, a bounded wait for responsiveness, caching and defaults for resilience, and local evaluation for the busiest service. Each simple habit covered a different risk, and together they turned a nerve-racking launch into a routine one.

26The Same Idea in the Wider World

Preparing a client library carefully at startup is a habit found across the whole industry.

Every service that offers a client library asks you to configure it at startup, and the same few questions repeat: which account, which address, how long to wait, what to do on failure, and what to remember. Recognising the pattern makes any new library easier to learn. The examples below describe publicly known styles in general terms, not any company’s private design.

Databases

Connection pools

Database libraries are set up once with an address, credentials and time limits, then shared by the whole program, because opening connections repeatedly is slow.

Payments

Payment libraries

Payment providers ask you to configure a secret key on servers and a public key in browsers, with separate test and live keys, exactly like the key split described here.

Monitoring

Telemetry agents

Monitoring libraries start early, batch their reports and send them on a timer, so they add little to the app’s startup cost.

Maps

Map and location libraries

These load once, cache what they can, and degrade gracefully when the connection is poor.

Config

Remote configuration

Large companies have long used remote settings that apps fetch at startup, cache locally and refresh in the background, with built-in defaults as a safety net.

Standards

OpenFeature

An open standard for flag clients lets an application talk to a common interface while a small provider connects it to a specific service.

The shared pattern

Across all of these, the same habits repeat. Configure once. Keep secrets on servers. Set time limits. Provide fallbacks. Remember what you learned. Report what happened. Once you know these habits, any new client library feels like a familiar room with different furniture.

Analogy

Moving into a rented flat, you check the same things every time: which keys open which doors, where the fuse box is, what to do if the heating fails. The flat changes, but the checklist does not. SDK initialization is that checklist for software.

Lessons you can reuse

  • Configure a client library once, in one place.
  • Separate test credentials from live ones.
  • Always know what your app does when the service is unreachable.
  • Prefer a small wrapper around third-party libraries, so changing them is easy.
  • Measure startup on real devices, not only on a fast office network.
Learn to start one client library well, and you have learned how to start them all.

27Limits: What Initialization Cannot Do

Knowing a tool’s limits is as valuable as knowing its strengths.

It cannot make a slow network fast

Initialization can hide delay with caches, defaults and bounded waits, but it cannot make a bad connection good. Users in poor coverage will sometimes start from saved flags or defaults, and your design should accept that gracefully.

It cannot guarantee instant freshness

Flags change in the dashboard, are published to the serving layer, and then reach each app by timer, live update or next launch. This takes a short time. Do not build features that need every user to see a change at the same millisecond. For strict coordination, use tools built for it.

It cannot protect secrets on a device

Anything inside a mobile app or web page can be inspected. A client-side key is safe to expose only because it can do very little. Flag values delivered to a device can be seen and possibly altered by the person holding it, so never use a client-side flag as the only guard for a sensitive action. Enforce permissions on your server.

It is not a user database

Traits exist to drive flag decisions. They are not a place to store customer profiles. Keep real customer records in your own systems.

It is not a substitute for testing

Flags make careful releases easier, but they do not remove bugs. Code behind a flag still needs tests in both its on and off states.

You want toUseNot
Start fast on a poor networkCache, defaults and a bounded waitAn unbounded wait for fresh flags
Guard a sensitive actionServer-side permission checksA client-side flag
Decide at huge volume on a serverLocal evaluation with a secret keyRemote lookup for every request
Coordinate machines at an exact momentLocks and queuesA flag flip
Store customer profilesYour own databaseIdentity traits
!
Tip

If a design feels awkward, step back and ask whether you are using flags for what they do best: fast, gradual, reversible control over what users see.

28A Plain-English Glossary

Quick definitions of the words used in this guide.

Term

SDK

A ready-made code library that makes using a service easy.

Term

Initialization

The one-time setup that connects an SDK to a service and prepares it for use.

Term

Environment key

The string that tells Flagsmith which environment an app belongs to.

Term

Client-side key

A public key that is safe to place in apps and can only read flags.

Term

Server-side key

A secret key for trusted backends only.

Term

Default value

The answer used when the SDK cannot get a real one.

Term

Timeout

The longest time you will wait for a reply.

Term

Backoff

Waiting longer between each retry so a struggling service is not overwhelmed.

Term

Time to live

How long a cached copy counts as fresh enough.

Term

Identity and trait

One user known by an ID, and a small fact about that user.

Term

Segment

A group of users defined by rules over traits.

Term

Remote evaluation

Asking the service to decide the flags for you.

Term

Local evaluation

Downloading the rules once and deciding on your own machine.

Term

Environment document

The compact bundle of all flags and rules for one environment.

Term

Offline mode

Running with flag data supplied from a file, with no network calls.

Term

Edge proxy

A component you run near your apps that caches environment data and answers SDK requests.

Term

Thundering herd

A sudden crowd of requests all arriving at once.

Term

Service level objective

A measurable target for how well a service should perform.

29Upgrading SDKs and Living With Change

Libraries evolve, and your startup code has to evolve with them.

Why upgrades happen

SDKs receive improvements regularly: new features, performance fixes, better error handling and security patches. Staying reasonably current means you benefit from these, and you avoid the painful situation of jumping across many versions at once. The risk is that an upgrade changes how a setting behaves, renames something or removes an old option.

A safe upgrade routine

1

Read the release notes

Look for words such as deprecated, removed, renamed and changed. Note anything touching initialization settings.

2

Upgrade in a branch

Change the version in a separate branch, not directly in your main code line.

3

Run your startup tests

Repeat the unhappy-path experiments: no network, slow network, wrong key, recovery. Compare the behaviour with the old version.

4

Release gradually

Ship to staff or a small slice of users first, and watch initialization time and failure rate by SDK version.

5

Record what you learned

Write a short note about any behaviour that changed, for the next person who upgrades.

Protect yourself with a wrapper

If all your code talks to a small interface of your own, such as “is this feature on,” and only that interface talks to the SDK, then an upgrade or even a complete replacement touches one file instead of hundreds. This is the same idea as keeping all the plumbing behind one panel in a house. It also makes testing easy, because tests can supply a fake version of the interface with fixed answers.

Analogy

A travel adapter lets one charger work in many countries. If the wall sockets change, you swap the adapter and keep the charger. Your own small interface is the adapter, and the SDK is the plug shape for a given country.

Mobile apps are special

On servers, you control when new code runs. On phones, old versions of your app linger for months, because users do not update promptly. That means several SDK versions may be alive at once, all asking the same service for flags. Test new flags against the oldest app version you still support, and use an “app version” trait so you can hide features from versions that cannot display them.

!
Watch out

Pin SDK versions in your build files and upgrade deliberately. An automatic jump to a newer version during a routine build can change startup behaviour without anyone deciding it should.

Standards and portability

Some teams reduce lock-in by using OpenFeature, an open standard for how applications ask for flags. Your code talks to the standard interface, and a small provider connects it to Flagsmith. If you ever change flag services, the application code stays almost the same. Whether to adopt it is a judgement call: native SDKs may expose features more directly, while the standard offers freedom.

30Startup Runbook, Ninety-Day Plan and Cheat Sheet

Three practical tools to keep beside your team’s notes.

Part one: when startup goes wrong

A runbook is a short, step-by-step guide that a tired person can follow at three in the morning. Here is one for the day users report that the app is slow to open or shows the wrong features.

1

Check the dashboards

Look at initialization time, failure rate and fallback usage. Note the regions, networks and app versions affected.

2

Look for recent changes

Open the Flagsmith audit log and your release history. Was a flag changed or a new app version shipped just before the trouble began?

3

Check the service status

Open the provider’s status page and your own network monitoring. Separate your problems from theirs.

4

Reverse the suspect change

If a flag change is a plausible cause, switch it back. Because flags are switches, this is usually faster than a new release.

5

Confirm recovery

Watch the same graphs and a test device. Remember the short publishing delay before apps see the repair.

6

Write it down

Record the cause, the fix and one improvement, such as a shorter wait budget or a better default.

Part two: a ninety-day plan

Days 1 to 30

Get the basics right

One shared initialization module, correct keys per environment, safe defaults and a timeout. Test with the network off.

Days 31 to 60

Make it fast and resilient

Add caching on clients, a bounded first-screen wait, identity handling on sign-in and sign-out, and monitoring of startup metrics.

Days 61 to 90

Make it sustainable

Introduce local evaluation where traffic justifies it, a wrapper interface, an upgrade routine, a runbook and a quarterly review of flags and defaults.

Part three: a one-page cheat sheet

  • Initialize once. One module, one shared instance.
  • Pick the key by place. Public key on devices, secret key on servers only.
  • Default to safe. Every flag has a fallback that keeps the stable behaviour alive.
  • Bound every wait. A timeout, a few retries, and a limited first-screen budget.
  • Cache on clients. Instant starts and resilience when the network fails.
  • Keep identities steady. Stable IDs give stable rollouts, and clear them on sign-out.
  • Share less data. Small, coarse, non-sensitive traits only.
  • Be ready before traffic. Servers using local evaluation wait for the first download.
  • Measure the real world. Startup time, failures and fallback rate, by region and version.
  • Upgrade on purpose. Read notes, test the unhappy paths, release gradually.

Pin this list beside your team’s runbook. New joiners can read it in two minutes, and experienced engineers will find that it settles most design arguments quickly. Good habits around the first few seconds of an app are what turn raw speed into a calm, dependable experience for the people who use your product, wherever in the world they happen to be.

One last piece of advice concerns patience. Nobody designs the perfect startup on the first attempt. Begin with a single environment, a couple of flags, safe defaults and a basic dashboard. Observe how the app behaves on real devices for a few weeks, note the surprises, and improve one habit at a time. Teams that grow their practice gradually end up with simpler, sturdier setups than teams that try to build everything before launch, because every addition is justified by a real need they have already seen.

Five questions to ask before you ship

Before any release that touches startup or flags, pause and answer five short questions. Doing so takes a few minutes and prevents most of the problems described in this guide.

  • Which key does this build use? Confirm the environment and the key type, and print the environment name in a startup log line.
  • What does the app do if the answer never arrives? Name the default for each new flag and confirm it is the safe behaviour.
  • How long will a user wait? State the wait budget in seconds and confirm it was tested on a slow connection.
  • Who is the user to Flagsmith? Check the identity and traits for signed-in, guest and signed-out states.
  • How will we know it worked? Decide the graph, log line or test device you will check after release.

These five questions work for a tiny change and for a company-wide migration alike. Teams that make them a habit rarely have dramatic startup failures, because small problems are noticed and fixed while they are still small, long before they can interfere with a launch, an experiment or an incident response. Treat your initialization code like any other product you ship: give it an owner, keep it small and well described, review it regularly, and remove whatever nobody needs any more.

Finally, write down what you learn. A short note beside the initialization module, explaining why the wait budget is what it is, why each default was chosen, and which incidents shaped the current settings, will save a future teammate from undoing a careful decision by accident. Settings that look arbitrary are changed casually, and settings that carry a clear reason are respected. A few thoughtful sentences left behind today are a gift to everyone who inherits your code, including your future self on a tired evening.

If you take only one idea from this guide, let it be that startup is a design decision, not an afterthought. Decide deliberately what your app shows in the first second, what it does when answers are late, and how it recovers. Everything else in this guide is detail in service of that decision.

31Frequently Asked Questions

Quick answers to the questions beginners ask most often.

Q1What is the minimum I need to initialize the SDK?
Usually just the environment key, with the hosted service address built in. Anything beyond that, such as defaults, timeouts and caching, improves resilience and speed, and is strongly recommended for production.
Q2How many times should I initialize?
Once per app run, in one place, sharing the instance everywhere. Repeated initialization wastes requests and discards stored flags.
Q3Which key goes in my mobile app?
Only the client-side environment key. It is designed to be public and limited to reading flags. Never ship a server-side key inside an app or website.
Q4What happens if Flagsmith is unreachable at startup?
A well-configured SDK uses saved flags from a previous run if it has them, and otherwise your default values. The app keeps working. This is why defaults and caching matter so much.
Q5Should my app wait for flags before drawing the first screen?
Wait only briefly, and only if the first screen depends heavily on flags. A bounded wait of a second or two, followed by cache or defaults, protects users from both blank screens and flicker.
Q6How do I choose a good default?
Pick the safe, stable, well-tested behaviour, usually “off” for a new feature. Decide with your product team and test the app with the network switched off.
Q7Why does my app show different flags from the dashboard?
Common reasons are the short publishing delay, cached flags, a long refresh interval, the wrong environment key, or a segment or override that applies to your test user. Work through the troubleshooting order in this guide.
Q8Do I need to send an identity?
Only if flags should differ between users, or you run percentage rollouts. Without an identity you receive the general flags for the environment. With a stable identity you get consistent personalised results.
Q9What is local evaluation and should I use it?
It means a server downloads the rules and decides for each user itself. It is fast and reduces requests, and suits busy trusted backends. It needs the secret key, and changes appear only after the next refresh.
Q10How often should flags refresh?
Often enough that stale flags do no harm, and rarely enough to avoid wasted requests. Minutes are typical for ordinary features on clients, and tens of seconds for local evaluation on servers. Use live updates where supported and truly needed.
Q11Can my app work with no network at all?
Yes, with offline mode or saved flags. Offline mode reads flag data from a file you supply, which also makes automated tests repeatable.
Q12Is it safe to cache flags on a device?
Yes for ordinary flags, but treat saved data as readable by the device owner and clear identity-related data on sign-out, especially on shared devices.
Q13How do I know whether startup is healthy?
Measure initialization time, failure rate and how often the app starts from defaults, split by region and network. Set a target and alert when it is missed.
Q14What is the single most important habit?
Choose safe defaults and test them. If your app behaves well when it cannot get an answer, almost every other problem becomes mild.

32Summary and Key Takeaways

The whole guide on one page.

Key Takeaways

  • Initialize once, share everywhere. One setup at startup, one shared instance, and flags read from memory afterwards with no network cost.
  • The key decides everything. Use the public client-side key in apps and the secret server-side key only on servers, one per environment, selected automatically per build.
  • Defaults are your safety net. Choose the safe, stable behaviour for every flag and test the app with the network switched off.
  • Bound the wait. Use a short timeout, a few polite retries and a limited first-screen wait, then continue with cache or defaults.
  • Cache on clients, evaluate locally on busy servers. Saved flags give instant starts, and local evaluation gives fast decisions with fewer requests.
  • Be thoughtful with identity. Use stable, non-personal IDs and small, non-sensitive traits, and clear them on sign-out.
  • Watch it in the real world. Monitor initialization time, failures and fallback usage, set a target, and rehearse the unhappy paths before launch.