Kaiten

Feature Flags

Create & Manage Flags

Create, update, enable/disable, and delete feature flags via the REST API or the console.

Create a feature flag

Choose a flag type

TypeUse caseVariant values
booleanOn/off togglestrue / false
stringNamed modes, copy variantsStrings
numberLimits, ratios, sizesNumbers
objectConfiguration, A/B testingStructured JSON payloads

Define variants

Every flag needs at least one variant and a default. Each variant is { "name", "description", "value" }; the default is { "type": "basic", "value": "<variant name>" }. See Variants for details.

Create via the API or the console

curl -X POST http://localhost:6060/api/feature-flags \
  -H "Authorization: Bearer ksh_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Table Reservations",
    "slug": "table-reservations-enabled",
    "description": "Gates the table reservation UI.",
    "type": "boolean",
    "enabled": true,
    "event_name": "table-reservations-enabled.evaluated",
    "metadata": {},
    "variants": [
      { "name": "on", "description": "Reservation UI visible", "value": true },
      { "name": "off", "description": "Reservation UI hidden", "value": false }
    ],
    "default_variant": { "type": "basic", "value": "off" },
    "targetings": []
  }'

The response is 201 Created with the flag. Creating a slug that already exists in the organization is refused with 409 Conflict.

Open Feature Flags and click New Feature Flag. The page walks four steps — Basic Information, Variants Configuration, Default Variant and Targeting Rules — with the Enabled switch in its header, and ends on Create Feature Flag.

A boolean flag starts with two variants named true and false, whose values are locked: rename them — to on and off, as in the API example — if your code expects other names. Typing the name fills in the slug, so set a slug of your own after the name.


Flag properties

PropertyTypeRequiredDescription
namestringYesDisplay name (e.g. "Table Reservations")
slugstringNoURL-safe identifier (^[a-z0-9][a-z0-9-]*[a-z0-9]$, 2–100 characters), generated from the name with a random suffix if omitted. Unique per organization.
descriptionstringYesFree text; may be null
typestringYesboolean, string, number or object
enabledbooleanYesMaster switch — when false, always returns the default variant
event_namestringYesA label stored with the flag; evaluation events do not carry it
variantsobject[]YesThe possible values the flag can resolve to — each { "name", "description", "value" }
default_variantobjectYesServed when no rule matches or the flag is disabled — { "type": "basic", "value": "<variant name>" }, or a rollout_percentage / rollout_date form (Variants)
targetingsobject[]YesOrdered rules for per-instance resolution — [] for none (Targeting rules)
metadataobjectYesFree-form metadata attached to the flag — {} for none

Update a flag

PUT /feature-flags/{slug} replaces the whole definition — there is no partial update, so send every property, changed or not. The slug is the exception: send one to rename the flag, omit it to keep the current one — and a rename changes the key your code evaluates. The response is 204 No Content:

curl -X PUT http://localhost:6060/api/feature-flags/table-reservations-enabled \
  -H "Authorization: Bearer ksh_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Table Reservations",
    "slug": "table-reservations-enabled",
    "description": "Gates the table reservation UI.",
    "type": "boolean",
    "enabled": true,
    "event_name": "table-reservations-enabled.evaluated",
    "metadata": {},
    "variants": [
      { "name": "on", "description": "Reservation UI visible", "value": true },
      { "name": "off", "description": "Reservation UI hidden", "value": false }
    ],
    "default_variant": { "type": "basic", "value": "off" },
    "targetings": [
      {
        "type": "basic",
        "name": "Premium license",
        "rule": "__kaiten.license.familySlug == \"premium\"",
        "variant": "on"
      }
    ]
  }'

Open the flag and click Configure. The four steps of the creation page become tabs, with the Enabled switch in the header; Update Feature Flag sends the whole definition. The flag's own tabs are read-only: editing happens in Configure.


Enable / disable

The enabled field acts as a master switch:

enabledBehavior
trueTargeting rules are evaluated; matching rules return their variant
falseAll evaluations return the default_variant with reason DISABLED — no rule is evaluated

This lets you disable a flag without deleting its configuration.

# Disable a flag: read it, flip `enabled`, and PUT the whole definition back
curl -s http://localhost:6060/api/feature-flags/table-reservations-enabled \
  -H "Authorization: Bearer ksh_xxx" \
  | jq 'del(.id) | .enabled = false' \
  | curl -X PUT http://localhost:6060/api/feature-flags/table-reservations-enabled \
      -H "Authorization: Bearer ksh_xxx" \
      -H "Content-Type: application/json" \
      -d @-

On Feature Flags, switch to the List view: each card carries a switch, which asks for confirmation — the change applies to every evaluation of the flag, immediately. The Table view shows the state without a switch. On the flag itself, click Configure, use the Enabled switch in the header, and click Update Feature Flag.


Delete a flag

curl -X DELETE http://localhost:6060/api/feature-flags/table-reservations-enabled \
  -H "Authorization: Bearer ksh_xxx"

The console has no delete action for a flag: deleting one is an API call.

Deleting a flag is permanent. Any application code evaluating this flag receives an error response after deletion. Remove flag evaluation from your codebase first.


List and filter

curl http://localhost:6060/api/feature-flags \
  -H "Authorization: Bearer ksh_xxx"

The response is a page — items carrying each flag's full definition (variants, targetings, enabled state), hasMore, and a nextCursor to pass back as ?cursor= for the next page. limit defaults to 50 and caps at 200.


In the console

Flag list

The Feature Flags page shows four counters — Total Flags, Enabled, Disabled and With Targeting — above the flags, in one of two views:

  • Table — each flag's name and slug, its type, its enabled state, its variants, its targeting rules, and its metadata.
  • List — one card per flag, with its switch and three actions: Try it, View and Configure.
The Feature Flags page of Kaiten Sushi Shop in its Table view: four counters above seven flags, each with its type, its Enabled state, its variants and its targeting rule.The Feature Flags page of Kaiten Sushi Shop in its Table view: four counters above seven flags, each with its type, its Enabled state, its variants and its targeting rule.

Flag page

A flag's page is read-only. Its header carries the flag's state and type, and two actions, Try it and Configure:

TabContent
OverviewType, event name, slug, ID, status and owner; the default variant strategy; metadata
VariantsEach variant with its description, a preview of its payload, and whether the default uses it
TargetingThe rules in evaluation order, and the fallback step
Try it historyWhat Try it returned in this browser session — nothing there is stored
The page of the Delivery Tracking Enabled flag, on its Overview tab: Try it and Configure in the header, four figures, the tabs Overview, Variants, Targeting and Try it history, and the General Information card.The page of the Delivery Tracking Enabled flag, on its Overview tab: Try it and Configure in the header, four figures, the tabs Overview, Variants, Targeting and Try it history, and the General Information card.

Try it, on the flag's page and on each card of the List view, evaluates the flag through the API's OFREP endpoint, for a JSON context that must include targetingKey, and shows the reason, the value, the variant and the metadata of the response. It is an evaluation like any other, recorded in the organization's audit trail. Run from the flag's page, it is also added to Try it history for the session.

On this page