> ## Documentation Index
> Fetch the complete documentation index at: https://feather.mupeni.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Evaluation

> How flags are resolved at the edge and what each reason means.

## How evaluation works

Flag evaluation never hits the management API database on the hot path. Instead:

1. **SDK initialisation** — the SDK fetches the full flag bundle for your environment from the **Delivery API**. The bundle is a JSON snapshot of all flag configs, served from an edge cache and held in-process for 30 seconds.

2. **`evaluate()` call** — the rule engine runs entirely in your process against the cached bundle. No network I/O.

3. **Telemetry flush** — evaluation events are buffered in memory and flushed to the Management API asynchronously. Your application never waits for telemetry.

## Evaluation reasons

Every evaluation returns a `reason` alongside the resolved value:

| Reason              | Meaning                                                                                             |
| ------------------- | --------------------------------------------------------------------------------------------------- |
| `DISABLED`          | The flag's master `enabled` switch is `false`                                                       |
| `RULE_MATCH`        | A rule matched and its value was returned                                                           |
| `ROLLOUT`           | A rule matched but evaluation was gated by `rolloutPercentage` — this user is in the rollout bucket |
| `DEFAULT`           | No rule matched; `defaultValue` was returned                                                        |
| `CLIENT_RESTRICTED` | A `client` API key attempted to evaluate a flag with `clientSafe: false`                            |
| `FLAG_NOT_FOUND`    | The flag key does not exist in the bundle for this environment                                      |
| `ERROR`             | An unexpected error occurred in the engine — `defaultValue` was returned                            |

The engine **never throws**. Any unhandled error results in `{ reason: "ERROR", value: defaultValue }`.

## Evaluation context

Pass any attributes you want to target on:

```typescript theme={null}
const value = await client.evaluate("my-flag", {
  userId: "user_abc123",
  plan: "pro",
  country: "US",
  email: "alice@example.com",
  // ... any custom attribute
});
```

Attributes are matched against rule conditions. Unknown attributes are ignored.

## Bundle format

The cache key for an environment's flag bundle is:

```
env:{environmentId}:flags
```

The bundle is a JSON object mapping flag keys to their latest `FlagConfig`. The Delivery API reads this key on cold start, then serves from an in-process cache for subsequent requests within the same worker lifetime.

## Cold start path

On a cold start, the Delivery API performs at most **2 cache reads**:

1. `sdk:{keyHash}` — resolve the API key to `orgId` + `environmentId`
2. `env:{environmentId}:flags` — fetch the flag bundle

Subsequent evaluations in the same worker instance use the in-memory cache.
