Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: Target Flagship feature flags with structured evaluation context
description: Use nested objects, arrays, and null in Flagship evaluation context, with dot-path targeting and array membership operators.
date: 2026-10-23
---

import { TypeScriptExample } from "~/components";

[Flagship](/flagship/) supports nested objects, arrays, and `null` in evaluation context. Pass user profiles and tag lists directly, then target nested attributes without flattening your application data.

For example, pass a profile and tags when evaluating a flag through the Workers binding:

<TypeScriptExample>

```ts
const enabled = await env.FLAGS.getBooleanValue("new-checkout", false, {
targetingKey: "user-42",
profile: { plan: "enterprise" },
tags: ["beta", "early-access"],
});
```

</TypeScriptExample>

A targeting rule can combine `profile.plan equals "enterprise"` with `tags has "beta"` to serve the feature to enterprise users in the beta group. Use dot-separated paths for nested attributes and the `has` and `not_has` operators for array membership. Percentage rollouts can also use a nested identifier, such as `profile.id`, for consistent user assignment.

Structured context works through the Workers binding, the evaluation REST API with a JSON `POST` body, and the TypeScript, Python, and Go OpenFeature SDKs from version `0.6.0`. The SDKs automatically use `POST` when HTTP evaluation requires structured context.

Refer to [targeting rules](/flagship/targeting/), the [evaluation API](/flagship/reference/evaluation-api/), and [SDK context support](/flagship/sdk/#context-support) for usage and supported values.
2 changes: 2 additions & 0 deletions src/content/docs/flagship/binding/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export default {
async fetch(request: Request, env: Env): Promise<Response> {
const enabled = await env.FLAGS.getBooleanValue("new-feature", false, {
userId: "user-42",
Comment thread
madhugb marked this conversation as resolved.
profile: { plan: "enterprise" },
tags: ["beta"],
});
return new Response(enabled ? "Feature on" : "Feature off");
},
Expand Down
36 changes: 26 additions & 10 deletions src/content/docs/flagship/binding/types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ products:
- flagship
---

The Flagship binding uses the following TypeScript types. These are available from the `@cloudflare/workers-types` package after running `npx wrangler types`.
The Flagship binding uses the following TypeScript types. Generate binding types with `wrangler types` or use the `@cloudflare/workers-types` package.

## `Flagship`

Expand All @@ -24,12 +24,26 @@ Refer to the [methods reference](/flagship/binding/methods/) for the full list o

## `FlagshipEvaluationContext`

A record of attribute names to values passed for [targeting rules](/flagship/targeting/). Use this to provide user attributes such as user ID, country, or plan type.
A record of attributes passed to [targeting rules](/flagship/targeting/). Values can recursively contain arrays and objects.

```ts
type FlagshipEvaluationContext = Record<string, string | number | boolean>;
type FlagshipEvaluationContextValue =
| string
| number
| boolean
| null
| FlagshipEvaluationContextValue[]
| { [key: string]: FlagshipEvaluationContextValue };

type FlagshipEvaluationContext = Record<string, FlagshipEvaluationContextValue>;
```

Numbers must be finite. The binding rejects `NaN`, `Infinity`, unsupported objects, and cyclic values.

The runtime also accepts valid JavaScript `Date` values. The binding normalizes each date to an ISO 8601 string. Invalid dates produce an `INVALID_CONTEXT` error.

Serialize `Date` values to ISO 8601 strings before passing them to the binding in TypeScript. The context type describes JSON values and does not include `Date`.

## `FlagshipEvaluationDetails`

Returned by the `*Details` methods. Contains the evaluated value and metadata about how Flagship resolved the flag.
Expand All @@ -41,15 +55,17 @@ interface FlagshipEvaluationDetails<T> {
variant?: string;
reason?: string;
errorCode?: string;
errorMessage?: string;
}
```

| Property | Type | Description |
| ----------- | -------- | -------------------------------------------------------------------------------------- |
| `flagKey` | `string` | The key of the evaluated flag. |
| `value` | `T` | The resolved flag value. |
| `variant` | `string` | The name of the matched variant, if any. |
| `reason` | `string` | Why the flag resolved to this value (for example, `"TARGETING_MATCH"` or `"DEFAULT"`). |
| `errorCode` | `string` | An error code if evaluation failed (for example, `"TYPE_MISMATCH"` or `"GENERAL"`). |
| Property | Type | Description |
| -------------- | -------- | -------------------------------------------------------------------------------------- |
| `flagKey` | `string` | The key of the evaluated flag. |
| `value` | `T` | The resolved flag value. |
| `variant` | `string` | The name of the matched variant, if any. |
| `reason` | `string` | Why the flag resolved to this value (for example, `"TARGETING_MATCH"` or `"DEFAULT"`). |
| `errorCode` | `string` | An error code if evaluation failed (for example, `"TYPE_MISMATCH"` or `"GENERAL"`). |
| `errorMessage` | `string` | A description of the evaluation error, if any. |

Refer to [evaluation reasons and error codes](/flagship/reference/evaluation-reasons/) for the full list of possible values.
15 changes: 13 additions & 2 deletions src/content/docs/flagship/concepts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ products:
- flagship
---

import { TypeScriptExample } from "~/components";

Flagship organizes feature flags into apps. You define flags with variants and targeting rules, then evaluate them within Cloudflare's global network.

## Overview
Expand Down Expand Up @@ -65,21 +67,30 @@ Refer to [Targeting rules](/flagship/targeting/) and [Operators](/flagship/targe

## Evaluation context

The evaluation context is a set of key-value attributes that describe the current user or request (for example, `userId`, `country`, `plan`).
The evaluation context describes the current user or request. It is an object whose top-level keys are attribute names.

Each value can be a string, finite number, boolean, `null`, array, or nested object. Arrays and objects can recursively contain the same value types.

You pass the context as the third argument to evaluation methods on the binding:

<TypeScriptExample>

```ts
const value = await env.FLAGS.getBooleanValue("new-checkout", false, {
userId: "user-42",
country: "US",
profile: { plan: "enterprise" },
tags: ["beta"],
});
```

</TypeScriptExample>

When using the [OpenFeature SDK](/flagship/sdk/), you pass context through the OpenFeature evaluation context object.

Flagship uses context attributes to match targeting rules and to determine percentage rollout bucketing. A consistent context (for example, the same `userId`) produces the same rollout result on every evaluation.

Evaluation context is input to an evaluation. It is separate from [JSON flag variants](#variants), which are values returned by an evaluation.

Avoid sending sensitive data in evaluation context. Only include attributes needed by targeting rules or rollout bucketing.

## Flag propagation
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/flagship/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Use the official OpenFeature SDKs to evaluate flags from Workers, Node.js, brows

<Feature header="Targeting rules" href="/flagship/targeting/" cta="Learn about targeting">

Serve different flag values based on user attributes. Rules support 11 comparison operators, logical AND/OR grouping, and sequential evaluation.
Serve different flag values based on user attributes. Rules support 13 comparison operators, logical AND/OR grouping, and sequential evaluation.

</Feature>

Expand Down
4 changes: 2 additions & 2 deletions src/content/docs/flagship/reference/api-reference.mdx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
pcx_content_type: navigation
title: API reference
description: API endpoints for managing Flagship apps, flags, and targeting rules.
description: API endpoints for managing and evaluating Flagship apps, flags, and targeting rules.
products:
- flagship
external_link: /api/resources/flagship/
sidebar:
order: 3
order: 4
---
51 changes: 51 additions & 0 deletions src/content/docs/flagship/reference/evaluation-api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
pcx_content_type: reference
title: Evaluation API
description: Evaluate flags with scalar query or structured JSON context.
sidebar:
order: 3
products:
- flagship
---

import { APIRequest } from "~/components";

Use the evaluation API when you cannot use the [Workers binding](/flagship/binding/). The API accepts query parameters or a JSON request body.

## Send scalar query context

The [`GET` endpoint](/api/resources/flagship/subresources/apps/subresources/evaluate/methods/get/) accepts context attributes as query parameters. Use it for scalar context values.

Flagship coerces unambiguous number and boolean query values. For example, `42` becomes a number and `true` becomes a boolean. Other values remain strings.

JSON-looking query values remain strings. A value such as `{"plan":"enterprise"}` does not create a nested object.

## Send structured JSON context

Use `POST` to send nested objects, arrays, or `null`. The following request evaluates `new-checkout` with structured context:

<APIRequest
path="/accounts/{account_id}/flagship/apps/{app_id}/evaluate"
method="POST"
json={{
flagKey: "new-checkout",
context: {
targetingKey: "user-42",
profile: { plan: "enterprise" },
tags: ["beta"],
},
}}
/>

The `POST` response contains the same fields as `GET`:

```json
{
"flagKey": "new-checkout",
"value": true,
"variant": "on",
"reason": "TARGETING_MATCH"
}
```

Invalid context returns a `400` response. Refer to [Limits](/flagship/reference/limits/) and [evaluation error codes](/flagship/reference/evaluation-reasons/#error-codes) for details.
10 changes: 8 additions & 2 deletions src/content/docs/flagship/reference/evaluation-reasons.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ When an evaluation error occurs, the method returns the default value you provid
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TYPE_MISMATCH` | The flag's variant type does not match the requested type. For example, calling `getBooleanValue` on a flag whose variant is a string. The default value is returned. |
| `FLAG_NOT_FOUND` | The specified flag key does not exist in the app. The default value is returned. |
| `INVALID_CONTEXT` | The evaluation context contains unsupported values, such as objects or arrays in HTTP evaluation. The default value is returned. |
| `INVALID_CONTEXT` | The context has an invalid shape or unsupported value, contains a non-finite number or cycle, or exceeds a limit. |
| `PARSE_ERROR` | The SDK received an invalid evaluation response. The default value is returned. |
| `GENERAL` | An unexpected error occurred during evaluation, such as a timeout or network failure. The default value is returned. |

## Invalid context behavior

Binding `*Details()` methods return the supplied default value for invalid context. They set `reason` to `ERROR`, `errorCode` to `INVALID_CONTEXT`, and include an `errorMessage`.

The direct data-plane HTTP `POST` endpoint returns a `400` response instead. Refer to [Evaluation API](/flagship/reference/evaluation-api/) for a request example.

## Example

The following example inspects evaluation details returned by `getBooleanDetails`:
Expand Down Expand Up @@ -69,7 +75,7 @@ switch (details.reason) {
}

if (details.errorCode) {
console.error(`Evaluation error: ${details.errorCode}`);
console.error(`Evaluation error: ${details.errorCode}`, details.errorMessage);
}
```

Expand Down
19 changes: 16 additions & 3 deletions src/content/docs/flagship/reference/limits.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
pcx_content_type: reference
title: Limits
description: Platform limits for Flagship, including maximum apps per account, flags per app, condition nesting depth, and configuration size.
description: Platform and evaluation context limits for Flagship apps, flags, rules, and requests.
sidebar:
order: 1
products:
Expand All @@ -20,17 +20,30 @@ Flagship enforces the following limits.
| Condition attribute names | 64 chars |
| Condition string values | 256 chars |
| Variant value size | 10 KB |
| Condition nesting depth | 5 levels |
| Condition grouping depth | 5 levels |
| Flag description | 512 chars |
| Flag configuration size per app | 25 MB |

:::note
The apps-per-account and flags-per-app limits are soft limits. If your use case requires higher limits, contact Cloudflare support.
:::

## Evaluation context limits

The following limits apply to each evaluation context:

| Feature | Limit | Scope |
| ------------------------------- | ------------- | ---------------------------------------- |
| Top-level attributes | 100 | All evaluation paths |
| Top-level key length | 1–256 chars | All evaluation paths |
| Value nesting depth | 10 levels | All evaluation paths |
| Serialized UTF-8 JSON size | 32 KiB | All evaluation paths |
| Values visited during traversal | 10,000 values | Data-plane HTTP and Workers binding only |

## Notes

- Condition nesting depth counts from the top-level condition group. A flat list of conditions (no nesting) has a depth of 1.
- Condition grouping depth counts from the top-level condition group. A flat list of conditions has a depth of one.
- Context value nesting and attribute path traversal use separate limits. Targeting attribute paths can contain up to five segments.
- Flag keys, app names, condition set names, and variant keys can contain letters, numbers, hyphens, and underscores.
- All variants on a flag must use the same value type: boolean, string, number, or JSON.
- Flag configuration size refers to the total serialized size of all flags within a single app, including their variants and rules.
5 changes: 4 additions & 1 deletion src/content/docs/flagship/reference/wrangler-commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ Conditions compare attributes from the evaluation context with rule values. The
```sh
--rule "serve=on; when=plan equals pro"
--rule "serve=on; when=country in [US,CA,UK]"
--rule "serve=on; when=tags has beta"
--rule "serve=off; when=email ends_with @example.com"
--rule "serve=strict; when=score less_than 20"
```
Expand All @@ -248,7 +249,7 @@ Use `AND` and `OR` to combine conditions. `AND` has higher precedence than `OR`.
--rule 'serve=on; when=country in ["US","CA"]'
```

For `in` and `not_in`, pass a bracketed list. Wrangler rejects malformed lists, empty list items, unterminated quotes, and unbalanced brackets before sending the request.
For `in` and `not_in`, pass a bracketed list. For `has` and `not_has`, pass the scalar array member to find. Wrangler rejects malformed lists, empty list items, unterminated quotes, and unbalanced brackets before sending the request.

Use `--rule-json` for deeply nested logical groups or if you prefer to pass the API rule shape directly. Wrangler validates `--rule-json` against the Flagship rule schema and rejects unknown or conflicting fields.

Expand Down Expand Up @@ -578,6 +579,8 @@ wrangler flagship flags evaluate <APP_ID> premium-banner \

Context values are sent to the evaluation endpoint as strings. Use the same attribute names that your targeting rules expect.

JSON-looking `--context` values remain strings. Wrangler does not create nested objects or arrays from these values.

Evaluation output includes:

| Field | Description |
Expand Down
6 changes: 6 additions & 0 deletions src/content/docs/flagship/sdk/client-provider.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ if (showBanner) {
| `retryDelay` | `number` | No | Delay between retries in milliseconds. Defaults to `1000` and is capped at `30000`. |
| `prefetchFlags` | `string[]` | Yes | Flag keys to fetch on initialization and on every context change. Flags not in this list return `FLAG_NOT_FOUND` at evaluation time. |

## Evaluation context

From version `0.6.0`, the client provider accepts strings, finite numbers, booleans, `null`, nested objects, and arrays. It normalizes valid `Date` values to ISO 8601 strings, including within objects and arrays.

During initialization and context changes, the provider sends structured context using `POST` with a JSON body. Context containing only strings, numbers, booleans, or dates uses `GET` query parameters. JSON-looking strings remain strings and do not create nested context.

## When to use the client provider

Use the client provider in browser applications, single-page apps, or any client-side JavaScript environment.
Expand Down
4 changes: 3 additions & 1 deletion src/content/docs/flagship/sdk/go.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,6 @@ The cache is per-provider instance, guarded by a mutex for concurrent use, and c

## Evaluation context

Context attributes are sent as URL query parameters. Supported values are strings, numeric types, booleans, and `time.Time`. `nil` values are skipped. Maps, slices, structs, and other complex values return `INVALID_CONTEXT` through OpenFeature and do not trigger an HTTP request.
From version `0.6.0`, context attributes can contain strings, finite numeric values, booleans, `nil`, maps with string keys, slices, and arrays. The provider recursively normalizes `time.Time` values to RFC 3339 strings.

The provider sends structured context using `POST` with a JSON body. Context containing only strings, numbers, booleans, or times uses `GET` query parameters. Unsupported values, such as other structs, and non-finite numbers return `INVALID_CONTEXT` through OpenFeature without triggering an HTTP request.
18 changes: 18 additions & 0 deletions src/content/docs/flagship/sdk/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,24 @@ Flagship SDKs are organized by language. The TypeScript SDK has separate setup g
If you are running inside a Cloudflare Worker, the [binding](/flagship/binding/) is the recommended approach because it avoids HTTP overhead. You can also [pass the binding to the OpenFeature SDK](/flagship/sdk/server-provider/) to get the best of both. Use the SDK without a binding when running in non-Worker runtimes like Node.js or the browser.
:::

## Context support

The TypeScript, Python, and Go SDKs support structured context from version `0.6.0`. Context support depends on the evaluation client and transport:

| Client or API | Context support |
| -------------------------- | ----------------------------------------------------------------- |
| Direct Workers binding | Recursive JSON values; valid `Date` values normalize to strings |
| TypeScript server provider | Recursive JSON values and `Date`, with binding or HTTP evaluation |
| TypeScript client provider | Recursive JSON values and `Date` |
| Python provider | Recursive JSON values and `datetime` |
| Go provider | Recursive JSON values and `time.Time` |
| Wrangler | String values from each `--context` argument |
| Evaluation API `POST` | Recursive JSON values |

The SDKs send structured context over HTTP using `POST`. Context containing only strings, numbers, booleans, or dates uses `GET` query parameters. Dates normalize to strings, including within nested objects and arrays.

Use the [evaluation API `POST` endpoint](/flagship/reference/evaluation-api/#send-structured-json-context) when sending structured context without an SDK.

## Installation

For TypeScript server-side usage:
Expand Down
Loading
Loading