Kaiten

Feature Flags

Variants

Define the possible values a feature flag can resolve to — from boolean toggles to object payloads.

What are variants?

Every feature flag defines a set of variants — the possible values it can resolve to. When a flag is evaluated, it returns exactly one variant based on targeting rules or the default.

Each variant has:

  • A name — a unique identifier within the flag (e.g. "on", "control", "treatment-a")
  • A description — free text shown in the console
  • A value — the payload, matching the flag's type (boolean, string, number, or object)

Boolean variants

The example below defines two variants with boolean payloads:

{
  "variants": [
    { "name": "on", "description": "Feature visible", "value": true },
    { "name": "off", "description": "Feature hidden", "value": false }
  ],
  "default_variant": { "type": "basic", "value": "off" }
}

Use boolean flags for:

  • Feature gates (enable/disable a capability)
  • Kill switches (disable a broken feature)
  • Gradual rollouts (target specific instances)

Object variants

For structured configuration, variants carry JSON payloads. This suits A/B testing, multi-variant experiments, and per-customer configuration.

{
  "variants": [
    {
      "name": "control",
      "description": "Current banner",
      "value": {
        "bannerText": "Welcome!",
        "bannerColor": "#000000"
      }
    },
    {
      "name": "treatment-a",
      "description": "Promotional banner",
      "value": {
        "bannerText": "Special Offer!",
        "bannerColor": "#ff0000"
      }
    },
    {
      "name": "treatment-b",
      "description": "Feature announcement banner",
      "value": {
        "bannerText": "New Feature!",
        "bannerColor": "#00ff00"
      }
    }
  ],
  "default_variant": { "type": "basic", "value": "control" }
}

Use object flags for:

  • A/B testing with different configurations
  • Tiered feature configurations
  • UI customization per customer segment

Default variant

Every flag must have a default_variant. This is what is served when:

  1. The flag is disabled (enabled: false) — reason DISABLED
  2. No targeting rule matches the evaluation context — reason DEFAULT (or, for a basic default, STATIC when the flag has no rules at all)

An evaluation whose context fails validation — no targetingKey — serves no variant: it fails with the error code PROVIDER_FATAL.

The default takes one of three forms, the same three a targeting rule can serve:

FormShapeBehavior
basic{ "type": "basic", "value": "off" }One fixed variant, named by its name
rollout_percentage{ "type": "rollout_percentage", "distribution": { "on": 20, "off": 80 } }A weighted split across variants — reason SPLIT when the flag has no rules, DEFAULT otherwise
rollout_date{ "type": "rollout_date", "start": { "date": "…", "percentage": 0, "variant": "off" }, "end": { "date": "…", "percentage": 100, "variant": "on" } }A percentage ramp from the start variant to the end variant between two dates — reason SPLIT when the flag has no rules, DEFAULT otherwise

Rules for variants

RuleDetail
Unique namesKeep variant names unique within a flag: the API does not refuse a duplicate, and an evaluation serves the value of the last variant of that name
Three required fieldsEvery variant carries name, description, and value
Consistent value typesKeep every variant's value in the flag's type — boolean, string, number, or object
Default must existA basic default's value must be the name of one of the defined variants; a rollout default's distribution or steps must name defined variants

Variant resolution flow

Evaluation request
  │
  ├── Flag disabled? → return default_variant (DISABLED)
  │
  ├── Evaluate targeting rules (top → bottom):
  │   ├── Rule 1 matches? → return rule's variant
  │   ├── Rule 2 matches? → return rule's variant
  │   └── No match → return default_variant (DEFAULT)
  │
  └── Response: { key, variant, value, reason }

The reason field in the response tells you why a particular variant was returned:

ReasonMeaning
TARGETING_MATCHA targeting rule matched and served a basic variant
SPLITA rollout_percentage or rollout_date distribution chose the variant
DEFAULTRules exist but none matched; the default was served
STATICThe flag has no rules; the default was served
DISABLEDFlag is disabled; the default was served without evaluating any rule
ERRORThe context failed validation (no targetingKey); no variant was served. The response carries the error code PROVIDER_FATAL instead of a reason; ERROR is the reason the recorded evaluation carries

Variant names are what OpenFeature SDKs surface as the variant of a result. Keep them short and descriptive — they appear in evaluation responses and logs.


Managing variants in the console

A flag's Variants tab is read-only: it lists each variant with its description, a preview of its payload, and whether the default uses it. Variants are edited in Configure, on Variants Configuration:

  • Add a variant with Add Variant, and give it a name, a description and a value.
  • Edit a variant in place — a rule that names a variant you rename must be updated with it.
  • Delete a variant, after a confirmation.

A boolean flag is the exception: it keeps exactly two variants, named true and false when the flag is created, whose values are locked. They can be renamed, but variants cannot be added or deleted. The default is chosen on the next step, Default Variant. Update Feature Flag saves the whole definition.

The Variants tab of the Delivery Tracking Enabled flag: the variants on and off with their descriptions and payload previews, true and false, and the Default mark on off.The Variants tab of the Delivery Tracking Enabled flag: the variants on and off with their descriptions and payload previews, true and false, and the Default mark on off.

On this page