Flags Evaluation
Feature Flags Overview
A flag is a named switch with a kind and a per-environment config. This page covers what a flag is, what states it holds, and exactly how a value gets chosen at evaluation time.
Flag kinds
Every flag is one of four kinds. The kind fixes the type of valueOn, valueOff, and defaultValue.
| Kind | Serves | Example value |
|---|---|---|
boolean | On/off gate | true |
string | A variant name or label | "variant-b" |
number | A tunable value | 25 |
json | A structured config blob | { "limit": 100 } |
States
Within an environment, a flag carries three states that gate what it serves:
- enabled, the on/off master switch for the environment. Off means the off value is served to everyone.
- rolloutPct, 0–100. The share of users who get the on value when no targeting rule decides for them. See Rollouts.
- killed, an emergency override that serves OFF to 100% of traffic in seconds, independent of the above. See Kill Switch.
defaultValue behavior
Two defaults exist and they are not the same thing:
- The flag's
defaultValueis served by the edge when the flag is missing or archived, a server-side fallback. - The
defaultyou pass toflag()is returned by the SDK on any failure, network error, timeout, unknown key. The call never throws.
Always pass a default
Because
flag() returns your default on any failure, your code has a deterministic answer even when ShipOS is unreachable. Treat it as the value your app runs on when nothing else is known.flag() vs flagDetail()
flag() returns just the value. flagDetail() returns the value plus why, the reason, the variation served, and, for percentage gates, the matched rule and the user's bucket.
const value = await shipos.flag("checkout-v2", {
userId: "u_42",
default: false,
});
// => true
const detail = await shipos.flagDetail("checkout-v2", { userId: "u_42" });
// => {
// value: true,
// reason: "rule_match",
// variation: "on",
// ruleId: "rule_pro_users",
// bucket: 37
// }How a value is chosen
At evaluation time the edge composes the environment config into a single value in this order:
- Killed? Serve OFF to everyone. Stop.
- Not enabled? Serve the off value. Stop.
- Targeting rules, evaluated top to bottom. The first rule whose conditions all match decides the value, optionally gated by that rule's own
rolloutPct. See Targeting. - No rule matched? Fall back to the base
enabled+rolloutPct, a stable percentage bucket on the user decides on vs. off.
Reading more
- Targeting Rules, serve by attribute.
- Percentage Rollouts, ramp with stable bucketing.
- Environments, dev, staging, prod, and promotion.
- Kill Switch, force OFF in seconds.