---
title: Feature Flags module
description: Control-plane feature flags with groups, self-overrides, permissions, and SDK-side local evaluation.
section: Modules
order: 11
updatedAt: 2026-05-28
slug: modules/feature-flags
---
# 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:

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

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

Python:

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

Go:

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

Rust:

```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

| Endpoint | Returns |
| --- | --- |
| `GET /api/flags/status` | Module 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}/kill` | Group emergency kill |
| `PUT /api/flags/{key}/self-override` | Set the caller's self-override |
| `GET /api/flags/stream?project_id=...` | Server-sent update stream |

Product page: [Feature Flags](/product/modules/feature-flags).