{
  "slug": "modules/feature-flags",
  "title": "Feature Flags module",
  "description": "Control-plane feature flags with groups, self-overrides, permissions, and SDK-side local evaluation.",
  "url": "https://cuitty.com/docs/modules/feature-flags",
  "markdown_url": "https://cuitty.com/docs/modules/feature-flags.md",
  "json_url": "https://cuitty.com/docs/modules/feature-flags.json",
  "frontmatter": {
    "title": "Feature Flags module",
    "description": "Control-plane feature flags with groups, self-overrides, permissions, and SDK-side local evaluation.",
    "order": 11,
    "section": "Modules",
    "updatedAt": "2026-05-28"
  },
  "headings": [
    {
      "depth": 1,
      "slug": "feature-flags-module",
      "text": "Feature Flags module"
    },
    {
      "depth": 2,
      "slug": "v2-model",
      "text": "V2 model"
    },
    {
      "depth": 2,
      "slug": "evaluation",
      "text": "Evaluation"
    },
    {
      "depth": 2,
      "slug": "sdk-examples",
      "text": "SDK examples"
    },
    {
      "depth": 2,
      "slug": "api",
      "text": "API"
    }
  ],
  "body_markdown": "# Feature Flags module\n\nThe 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.\n\n## V2 model\n\n- Flags remain stable keys such as `new_checkout` or `admin_panel`.\n- Groups collect related flags, so an operator can disable or kill every flag in a rollout area without editing each flag.\n- Group kill and flag kill are emergency stops and always evaluate false.\n- Owner/developer self-overrides can opt one actor in or out without changing the default rollout.\n- Route-level checks use the Feature Flags permission vocabulary and are designed to sit behind SpiceDB-backed project permissions.\n- Local and staging environments can inspect and toggle flags from the Cuitty toolbar once the toolbar is installed.\n\n## Evaluation\n\nSDK helpers evaluate locally using the same rule as the server and CUI preview:\n\n1. Killed or disabled groups return false.\n2. Killed flags return false.\n3. Active self-overrides return their stored value.\n4. Disabled flags return false.\n5. Non-empty cohort dimensions must match the evaluation context.\n6. 100% rollouts return true, 0% rollouts return false.\n7. Percentage rollouts use SHA-256 of `flagKey:userId`, bucketed into 0-99.\n\nSelf-overrides do not bypass a group kill switch.\n\n## SDK examples\n\nTypeScript:\n\n```ts\nconst flags = createFlagsPlugin();\ncuitty.use(flags);\n\nconst enabled = flags.isEnabled(\"new_checkout\", {\n  userId: \"user_123\",\n  env: \"staging\",\n  role: \"developer\",\n});\n```\n\nPython:\n\n```python\nenabled = client.flags.is_enabled(\n    \"new_checkout\",\n    user_id=\"user_123\",\n    env=\"staging\",\n    role=\"developer\",\n)\n```\n\nGo:\n\n```go\nenabled, err := client.Flags.IsEnabled(ctx, \"new_checkout\", cuitty.EvalContext{\n    \"userId\": \"user_123\",\n    \"env\": \"staging\",\n    \"role\": \"developer\",\n})\n```\n\nRust:\n\n```rust\nlet mut ctx = cuitty::plugins::flags::EvalContext::new();\nctx.insert(\"userId\".into(), \"user_123\".into());\nctx.insert(\"env\".into(), \"staging\".into());\nctx.insert(\"role\".into(), \"developer\".into());\n\nlet enabled = client.flags().is_enabled(\"new_checkout\", &ctx).await?;\n```\n\n## API\n\n| Endpoint | Returns |\n| --- | --- |\n| `GET /api/flags/status` | Module health |\n| `GET /api/flags?project_id=...` | Flags for a project |\n| `GET /api/flags/{key}?project_id=...` | A single flag |\n| `GET /api/flags/groups?project_id=...` | Groups for a project |\n| `POST /api/flags/groups/{key}/kill` | Group emergency kill |\n| `PUT /api/flags/{key}/self-override` | Set the caller's self-override |\n| `GET /api/flags/stream?project_id=...` | Server-sent update stream |\n\nProduct page: [Observe modules](/products/observe/modules).",
  "links_out": [
    "/products/observe/modules"
  ]
}