Skip to content

Flag concepts

A feature flag is a named switch you control from the dashboard (or the API) and read from your code. Flip it, target it, or roll it out gradually without redeploying.

Every flag defines a fixed set of variations: the possible values it can serve. Each variation has an idx (its position), a value, and an optional name. Evaluation always resolves to exactly one variation for a given context.

A boolean flag typically has two variations (true / false); a string or number flag can have as many as you need.

boolean

On/off switches. Read with boolVariation.

string

Named variants, copy, theme, cohort labels. Read with stringVariation.

number

Numeric config, limits, thresholds, prices. Read with numberVariation.

json

Structured config objects. Read with jsonVariation.

The type is set when you define the flag (POST /v1/flags). Read any flag with the typed matching method, the generic variation<T>(), or allFlags() to pull the whole set at once.

A flag’s on/off state, default variation, and targeting are configured per environment (for example production and development). The same flag key behaves differently in each, so you can enable a flag in dev while it stays off in production. The SDK reads the environment you initialize it with (environment option, defaults to production).

Within an environment, evaluation follows a fixed order:

  1. If the flag is off, serve its offVariation.
  2. If a targeting rule matches the context, serve that rule’s variation (or weighted rollout).
  3. Otherwise serve the fallthrough (a single variation or a weighted rollout).

Rules are clause-based: an attribute compared against values (attribute op values), or a segment match, combined with and/or. See Targeting and rollouts.

A segment is a reusable targeting group, define who’s in it once, then reference it from any flag’s rules. Change the segment and every flag that references it updates. See the segments API.

Each variation() call records an exposure: which context saw which variation, and batches it to Versuch for experiment analytics. Only the context key is sent (the server hashes it); attributes are never included. Disable with sendExposures: false.

Versuch resolves flags differently depending on where the SDK runs, and each model pairs with a key that is safe where it runs.

Browser, pre-evaluated

VersuchClient with a public key (vpk_live_… or csk_live_…). The server evaluates flags and returns a sanitized payload from /v1/client-config, resolved values only, no rules or segments cross the wire. Safe to ship in a browser bundle. See Browser SDK.

Server, local eval

VersuchServerClient with a secret key (vsk_live_… or ssk_live_…). Fetches the full compiled config from /v1/config once and evaluates every flag locally with the bundled engine, full rules and segments, zero per-call latency. See Server SDK.

The clients guard the boundary for you: the server client throws if it detects a browser, and the browser client throws if handed a secret key.

Flag variations
Environment config rules · rollout · fallthrough
Served value one variation
The browser receives the resolved value; the server runs this same path locally.

detail() returns not just the value but the reason it was served (off, a matched rule, or fallthrough) and the config version: useful for debugging why a context landed where it did.