Flag keys
Every flag has a key that is unique within its project. When evaluating a flag from an SDK, the key is fully-qualified with the project key:
For example, a flag with key charge-delivery-fee in the checkout project is referenced as:
useFlag('checkout.charge-delivery-fee', { customerId })
Keys are lowercase and may contain letters, numbers, dots, and hyphens. The project key is set when the project is created and cannot be changed.
Flag types
The flag type determines the shape of its value and how the SDK returns it. Set the type when creating the flag — it cannot be changed after creation without re-creating the flag.
| Type | SDK return type | Typical use cases |
|---|
boolean | bool / boolean | Feature gates, kill switches, A/B experiments |
string | string | UI variants, copy testing, configuration by name |
number | number / double | Numeric thresholds, price multipliers, capacity limits |
object | Record / object | Structured configuration payloads |
Requesting the wrong type (e.g. calling GetString on a number flag) returns the caller-supplied default with reason TYPE_MISMATCH. This is a programming error and should be caught in development.
Environments
Each flag is independently configured per environment. The same flag key can have different settings in development, staging, and production — different rollout percentages, different default values, different targeting rules.
checkout.charge-delivery-fee
├── development: disabled
├── staging: enabled, 10% rollout
└── production: enabled, 100% rollout
The SDK key you use determines which environment’s configuration is fetched. SDK keys are shown under Settings → Environments in the dashboard.
Enabled / disabled
A flag marked as disabled always returns its default value, regardless of rollout configuration or targeting rules. The reason code returned is STATIC.
Disabling a flag is the fastest way to globally turn off a feature — no code change, no deployment. The updated snapshot reaches SDKs within the next polling cycle (typically under two minutes).
Disabled flags are excluded from the snapshot entirely. The SDK treats them as not found and returns the caller-supplied default with reason FLAG_NOT_FOUND. For boolean flags the effect is identical since both paths return false.
Default value
The default value is what the SDK returns when:
- The flag is not found in the snapshot (flag disabled, not yet created, or wrong environment)
- No targeting rule matches and no rollout is configured
For boolean flags, the default is always false — there is no configuration option for this.
For non-boolean flags, the default value is set per environment in the dashboard’s Targeting tab and is included in the snapshot.
There are two separate defaults to understand:
| Default | Controlled by | When used |
|---|
| Flag default value (dashboard) | Dashboard, per environment | No rule matches and no rollout is configured |
| Caller default (SDK call site) | Code | Flag not in snapshot, type mismatch, SDK not ready |
The caller default takes precedence over the flag default when the SDK cannot perform evaluation at all (e.g. snapshot not yet loaded). In practice, for boolean flags these are always false.
Rollout
Rollout controls which users receive the flag’s active value when no targeting rule matches. Bucketing is deterministic: the same user always lands in the same bucket for the same flag, across all restarts and platforms.
Boolean flags
A single percentage (0–100%). Users within the bucket receive true; all others receive false (the default). Setting rollout to 0% disables the flag for all users while still counting as enabled. Setting it to 100% enables it for all users globally.
Non-boolean flags
A percentage-weighted distribution across two or more values. For example:
| Value | Weight |
|---|
"red" | 20% |
"blue" | 80% |
Users are deterministically bucketed: each user consistently receives the same value for the same flag. This is how A/B tests and gradual multi-value rollouts are implemented.
Rollout requires a bucketing key in the evaluation context (customerId, agentId, etc.). Without a bucketing key, the SDK cannot determine which bucket the user belongs to and returns the default value with MISSING_TARGETING_KEY.
Targeting rules
Rules let you override the rollout and serve specific values to specific users based on their attributes. Rules are evaluated in order — the first match wins. If no rule matches, evaluation falls through to rollout, then to the default value.
See Targeting for the full reference on operators, conditions, and rule structure.
Archiving
Archived flags are excluded from the snapshot and no longer evaluated. Archiving is a soft delete — the flag remains in the database and can be unarchived. It is distinct from disabling: disabling is for temporary deactivation; archiving is for flags that are permanently removed from the codebase.
Remove the flag evaluation call from code before archiving to avoid FLAG_NOT_FOUND responses showing up in your logs.