Skip to main content

Feature Flags module

Control-plane feature flags with groups, self-overrides, permissions, and SDK-side local evaluation.

Feature Flags module

The Feature Flags module is a control-plane module for rollout decisions, not just an SDK utility. It manages flag definitions, group-level rollout state, cohort gates, kill switches, owner/developer self-overrides, and transactional history from the same permissioned surface as the rest of Cuitty.

V2 model

  • Flags remain stable keys such as new_checkout or admin_panel.
  • Groups collect related flags, so an operator can disable or kill every flag in a rollout area without editing each flag.
  • Group kill and flag kill are emergency stops and always evaluate false.
  • Owner/developer self-overrides can opt one actor in or out without changing the default rollout.
  • Route-level checks use the Feature Flags permission vocabulary and are designed to sit behind SpiceDB-backed project permissions.
  • Local and staging environments can inspect and toggle flags from the Cuitty toolbar once the toolbar is installed.

Evaluation

SDK helpers evaluate locally using the same rule as the server and CUI preview:

  1. Killed or disabled groups return false.
  2. Killed flags return false.
  3. Active self-overrides return their stored value.
  4. Disabled flags return false.
  5. Non-empty cohort dimensions must match the evaluation context.
  6. 100% rollouts return true, 0% rollouts return false.
  7. Percentage rollouts use SHA-256 of flagKey:userId, bucketed into 0-99.

Self-overrides do not bypass a group kill switch.

SDK examples

TypeScript:

const flags = createFlagsPlugin();
cuitty.use(flags);

const enabled = flags.isEnabled("new_checkout", {
  userId: "user_123",
  env: "staging",
  role: "developer",
});

Python:

enabled = client.flags.is_enabled(
    "new_checkout",
    user_id="user_123",
    env="staging",
    role="developer",
)

Go:

enabled, err := client.Flags.IsEnabled(ctx, "new_checkout", cuitty.EvalContext{
    "userId": "user_123",
    "env": "staging",
    "role": "developer",
})

Rust:

let mut ctx = cuitty::plugins::flags::EvalContext::new();
ctx.insert("userId".into(), "user_123".into());
ctx.insert("env".into(), "staging".into());
ctx.insert("role".into(), "developer".into());

let enabled = client.flags().is_enabled("new_checkout", &ctx).await?;

API

EndpointReturns
GET /api/flags/statusModule health
GET /api/flags?project_id=...Flags for a project
GET /api/flags/{key}?project_id=...A single flag
GET /api/flags/groups?project_id=...Groups for a project
POST /api/flags/groups/{key}/killGroup emergency kill
PUT /api/flags/{key}/self-overrideSet the caller’s self-override
GET /api/flags/stream?project_id=...Server-sent update stream

Product page: Observe modules.