# Evaluation order

> The exact precedence the SDKs follow to resolve a flag.

When you call `enabled()` or `getValue()`, the SDK resolves the flag against the
cached config in a fixed order. Every SDK follows these exact steps — this
precedence is part of the cross-language parity contract.

Throughout, **enabled value** means `true` for a boolean flag, or the flag's
`enabled_value` (falling back to `default_value` if unset) for a non-boolean
(string / number / json) flag. **Default value** is the flag's `default_value`.

## The five steps

1. **Flag disabled → default value.** If the flag is off, return the default
   value immediately. Nothing else is considered.

2. **No user context → rollout-or-default.** If you didn't pass a `user`, there's
   no one to match rules against or to bucket. Return the enabled value only if
   the rollout is 100 (serve-everyone); otherwise the default value.

3. **Rule groups → enabled value.** With a user present, check the targeting
   groups in order. The first group whose conditions all match (AND within a
   group; OR across groups) returns the enabled value. A matched user gets the
   feature **regardless of the rollout percentage**.

4. **Rollout percentage.** If no rule matched and the user has a `user_id` (or
   `id`), bucket them: `sha256("{user_id}:{flag_key}") % 100`. Return the enabled
   value if the bucket is **less than** `rollout_pct`, otherwise the default. (At
   `rollout_pct = 100`, every bucket 0–99 is below 100, so everyone is included.)

5. **Otherwise → default value.** If nothing matched — no rule, and no usable
   `user_id` to bucket (so only a 100% rollout would have applied) — return the
   default value.

## In short

- **Off** beats everything → default.
- **A matching rule** beats the rollout → enabled.
- **The rollout** decides the rest → enabled if in-bucket, else default.
- **No way to decide** (no user / no id, rollout below 100) → default.

The default value is the safe fallback at every dead end, which is why it should
always be the conservative choice (usually your existing behaviour).

## Why no-context and no-id behave the same

Steps 2 and 5 both fall back to "enabled only if rollout is 100." A rollout needs
an id to bucket; without one, the only sensible interpretation of a partial
rollout is "not this caller," while a full rollout still means everyone. This
keeps a flag at 100% behaving like a simple on/off even when no user is passed.

## Next

- [Percentage rollouts](/docs/concepts/rollouts) — the bucketing in depth.
- [Rule operators](/docs/reference/operators) — what makes a condition match.
