---
title: Cloudflare Flagship
description: Flagship is Cloudflare's feature flag service. It lets you control feature visibility in your applications without redeploying code. Define flags with targeting rules and percentage-based rollouts, then evaluate them directly inside your Workers through a native binding.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/index.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Cloudflare Flagship

Ship features safely with feature flags.

Flagship is Cloudflare's feature flag service. It lets you control feature visibility in your applications without redeploying code. Define flags with targeting rules and percentage-based rollouts, then evaluate them directly inside your Workers through a [native binding](https://developers.cloudflare.com/flagship/binding/).

[OpenFeature ↗](https://openfeature.dev/) is the CNCF open standard for feature flag management. Flagship is compatible with OpenFeature, so you can use the [@cloudflare/flagship ↗](https://www.npmjs.com/package/@cloudflare/flagship) SDK from any JavaScript runtime — Workers, Node.js, or the browser — and swap providers without changing evaluation code.

Check out the [Get started guide](https://developers.cloudflare.com/flagship/get-started/) to create your first feature flag.

## Features

###  Worker binding 

Evaluate flags with a native Workers binding. Type-safe methods with automatic fallback to defaults.

[ Binding reference ](https://developers.cloudflare.com/flagship/binding/) 

###  OpenFeature SDK 

Use the [@cloudflare/flagship ↗](https://www.npmjs.com/package/@cloudflare/flagship) OpenFeature provider to evaluate flags from Workers, Node.js, or browsers. Switch from another flag provider by changing one line of configuration.

[ View SDK docs ](https://developers.cloudflare.com/flagship/sdk/) 

###  Targeting rules 

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

[ Learn about targeting ](https://developers.cloudflare.com/flagship/targeting/) 

###  Percentage rollouts 

Gradually release features to a percentage of users. Consistent hashing ensures the same user always receives the same flag value.

[ Learn about rollouts ](https://developers.cloudflare.com/flagship/targeting/percentage-rollouts/) 

###  Multi-type variations 

Flag variations can be booleans, strings, numbers, or structured JSON objects. Use object variations to deliver entire configuration blocks as a single flag.

[ Use Multi-type variations ](https://developers.cloudflare.com/flagship/concepts/) 

###  Flag management 

Create, update, and delete flags through the Cloudflare dashboard. Organize flags into apps that map to your projects or services.

[ Use Flag management ](https://developers.cloudflare.com/flagship/get-started/) 

---

## Related products

**[Workers](https://developers.cloudflare.com/workers/)** 

Build serverless applications on Cloudflare's global network. Flagship integrates natively with Workers through a binding.

**[KV](https://developers.cloudflare.com/kv/)** 

Store key-value data across Cloudflare's global network. Flagship uses this infrastructure to deliver flag configurations.

## More resources

[Developer Discord](https://discord.cloudflare.com) 

Connect with the Workers community on Discord to ask questions, show what you are building, and discuss the platform with other developers.

[@CloudflareDev](https://x.com/cloudflaredev) 

Follow @CloudflareDev on Twitter to learn about product announcements and what is new in Cloudflare Workers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}}]}
```

---

---
title: Get started
description: In this guide, you will create a feature flag in Flagship and evaluate it inside a Cloudflare Worker.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/get-started.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Get started

In this guide, you will create a feature flag in Flagship and evaluate it inside a Cloudflare Worker.

## Create an app and a flag

In this example, you will create a boolean flag called `new-checkout` that controls whether users see a new checkout experience.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/) and select your account.
2. Go to **Compute** \> **Flagship**.
3. Select **Create app**. Give the app a name that matches your project or service (for example, `checkout-service`).
4. Inside the app, select **Create flag**.
5. Create a boolean flag with the key `new-checkout`. Optionally, add [targeting rules](https://developers.cloudflare.com/flagship/targeting/) to control who sees the flag.
6. Turn on the flag and select **Save**.

## Add the Flagship binding to your Worker

Add the Flagship binding in your Wrangler configuration file so your Worker can evaluate flags through a binding.

* [  wrangler.jsonc ](#tab-panel-6855)
* [  wrangler.toml ](#tab-panel-6856)

JSONC

```

{

  "flagship": {

    "binding": "FLAGS",

    "app_id": "<APP_ID>",

  },

}


```

TOML

```

[flagship]

binding = "FLAGS"

app_id = "<APP_ID>"


```

Replace `<APP_ID>` with the app ID shown in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/flagship). The `binding` field sets the name you use to access Flagship in your Worker code. In this example, the binding is available as `env.FLAGS`.

After updating the Wrangler configuration, run `npx wrangler types` to generate TypeScript types for the binding.

## Evaluate the flag in your Worker

Use the `env.FLAGS` binding to evaluate the flag. The binding provides type-safe methods that return the flag value and fall back to the default you provide if evaluation fails.

* [  JavaScript ](#tab-panel-6857)
* [  TypeScript ](#tab-panel-6858)

JavaScript

```

export default {

  async fetch(request, env) {

    const url = new URL(request.url);

    const userId = url.searchParams.get("userId") ?? "anonymous";


    const showNewCheckout = await env.FLAGS.getBooleanValue(

      "new-checkout",

      false,

      { userId },

    );


    if (showNewCheckout) {

      return new Response("Welcome to the new checkout experience!");

    }


    return new Response("Standard checkout.");

  },

};


```

Explain Code

TypeScript

```

export default {

  async fetch(request: Request, env: Env): Promise<Response> {

    const url = new URL(request.url);

    const userId = url.searchParams.get("userId") ?? "anonymous";


    const showNewCheckout = await env.FLAGS.getBooleanValue(

      "new-checkout",

      false,

      { userId },

    );


    if (showNewCheckout) {

      return new Response("Welcome to the new checkout experience!");

    }


    return new Response("Standard checkout.");

  },

};


```

Explain Code

The third argument to `getBooleanValue` is the [evaluation context](https://developers.cloudflare.com/flagship/concepts/#evaluation-context). Flagship uses the context attributes to match targeting rules. In this example, the `userId` attribute is passed so that percentage rollouts and user-specific targeting work correctly.

## Deploy and test

Deploy your Worker:

Terminal window

```

npx wrangler deploy


```

Test flag evaluation by sending a request:

Terminal window

```

curl "https://<YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev/?userId=user-42"


```

Change the flag value or targeting rules in the dashboard and observe the updated response. Flag changes propagate globally within seconds.

## (Optional) Use the OpenFeature SDK

If you prefer the [OpenFeature ↗](https://openfeature.dev/) standard interface, or if you are running outside of a Cloudflare Worker, you can use the [@cloudflare/flagship ↗](https://www.npmjs.com/package/@cloudflare/flagship) SDK instead of the binding.

Install the SDK:

 npm  yarn  pnpm  bun 

```
npm i @cloudflare/flagship @openfeature/server-sdk
```

```
yarn add @cloudflare/flagship @openfeature/server-sdk
```

```
pnpm add @cloudflare/flagship @openfeature/server-sdk
```

```
bun add @cloudflare/flagship @openfeature/server-sdk
```

Evaluate flags using the OpenFeature client:

* [ With binding ](#tab-panel-6863)
* [ With app ID ](#tab-panel-6864)

Pass the Flagship binding directly to the provider. This avoids additional HTTP requests and is the recommended approach inside a Worker. Authentication is handled automatically through the binding.

* [  JavaScript ](#tab-panel-6861)
* [  TypeScript ](#tab-panel-6862)

JavaScript

```

import { OpenFeature } from "@openfeature/server-sdk";

import { FlagshipServerProvider } from "@cloudflare/flagship";


export default {

  async fetch(request, env) {

    await OpenFeature.setProviderAndWait(

      new FlagshipServerProvider({ binding: env.FLAGS }),

    );


    const client = OpenFeature.getClient();


    const showNewCheckout = await client.getBooleanValue(

      "new-checkout",

      false,

      { targetingKey: "user-42" },

    );


    return new Response(

      showNewCheckout ? "New checkout!" : "Standard checkout.",

    );

  },

};


```

Explain Code

TypeScript

```

import { OpenFeature } from "@openfeature/server-sdk";

import { FlagshipServerProvider } from "@cloudflare/flagship";


export default {

  async fetch(request: Request, env: Env): Promise<Response> {

    await OpenFeature.setProviderAndWait(

      new FlagshipServerProvider({ binding: env.FLAGS }),

    );


    const client = OpenFeature.getClient();


    const showNewCheckout = await client.getBooleanValue(

      "new-checkout",

      false,

      { targetingKey: "user-42" },

    );


    return new Response(

      showNewCheckout ? "New checkout!" : "Standard checkout.",

    );

  },

};


```

Explain Code

Use an app ID, account ID, and an API token when running outside of a Worker (for example, in Node.js). The provider makes HTTP requests to the Flagship evaluation endpoint. Generate an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) from your Cloudflare account with Flagship read permissions.

* [  JavaScript ](#tab-panel-6859)
* [  TypeScript ](#tab-panel-6860)

JavaScript

```

import { OpenFeature } from "@openfeature/server-sdk";

import { FlagshipServerProvider } from "@cloudflare/flagship";


await OpenFeature.setProviderAndWait(

  new FlagshipServerProvider({

    appId: "<APP_ID>",

    accountId: "<ACCOUNT_ID>",

    authToken: "<API_TOKEN>",

  }),

);


const client = OpenFeature.getClient();


const showNewCheckout = await client.getBooleanValue("new-checkout", false, {

  targetingKey: "user-42",

});


```

Explain Code

TypeScript

```

import { OpenFeature } from "@openfeature/server-sdk";

import { FlagshipServerProvider } from "@cloudflare/flagship";


await OpenFeature.setProviderAndWait(

  new FlagshipServerProvider({

    appId: "<APP_ID>",

    accountId: "<ACCOUNT_ID>",

    authToken: "<API_TOKEN>",

  }),

);


const client = OpenFeature.getClient();


const showNewCheckout = await client.getBooleanValue("new-checkout", false, {

  targetingKey: "user-42",

});


```

Explain Code

Refer to the [SDK documentation](https://developers.cloudflare.com/flagship/sdk/) for detailed setup instructions.

## Next steps

* Learn about [targeting rules](https://developers.cloudflare.com/flagship/targeting/) to serve different values based on user attributes.
* Explore the full [binding API reference](https://developers.cloudflare.com/flagship/binding/) for all evaluation methods.
* Read about [percentage rollouts](https://developers.cloudflare.com/flagship/targeting/percentage-rollouts/) for gradual feature releases.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/get-started/","name":"Get started"}}]}
```

---

---
title: Concepts
description: Flagship organizes feature flags into apps. You define flags with variations and targeting rules, then evaluate them within Cloudflare's global network.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/concepts.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Concepts

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

## Overview

Flagship feature flags go through three stages from creation to evaluation:

1. **Configure** — Create flags and targeting rules in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/) or through the API.
2. **Propagate** — Flagship automatically distributes your flag configuration across Cloudflare's global network within seconds.
3. **Evaluate** — Your Worker (or SDK) evaluates flags locally using the propagated configuration. There is no round-trip to a central server.

Flag changes take effect globally within seconds of saving. You do not need to redeploy your Worker or restart your application. If the dashboard is temporarily unavailable, flag evaluation continues to work using the last propagated configuration.

## Apps

An app is the top-level organizational unit in Flagship. It groups related flags together.

An app typically maps to a single project, service, or product surface. Each Cloudflare account can have multiple apps. For example, you might create one app for your marketing site and another for your API backend.

## Flags

A flag is a named feature toggle. Each flag has a key, a set of [variations](#variations), [targeting rules](#targeting-rules), and an enabled/disabled state.

Flag keys must be unique within an app. Keys can contain letters, numbers, hyphens, and underscores.

When a flag is disabled, it always returns the default variation regardless of any targeting rules.

## Variations

Variations are the possible values a flag can return. Each flag must have at least one variation, and one variation is designated as the default.

Flagship supports four variation types:

| Type        | Example                                                               |
| ----------- | --------------------------------------------------------------------- |
| Boolean     | on: true, off: false                                                  |
| String      | v1: "old-checkout", v2: "new-checkout"                                |
| Number      | low: 100, high: 1000                                                  |
| JSON object | premium: { "tier": "premium", "features": \["analytics", "export"\] } |

Use boolean flags for simple on/off toggles. Use string, number, or JSON object flags when you need to deliver configuration values or structured data.

## Targeting rules

Targeting rules control which variation a flag returns for a given request. Rules are evaluated in sequential order, and the first matching rule wins. If no rule matches, the default variation is returned.

Each rule contains:

* **Conditions** that compare an attribute from the [evaluation context](#evaluation-context) against a value using an operator.
* An optional **percentage rollout** that splits traffic across variations.
* A **variation** to serve when the rule matches.

Conditions within a rule can be grouped with `AND`/`OR` operators.

Refer to [Targeting rules](https://developers.cloudflare.com/flagship/targeting/) and [Operators](https://developers.cloudflare.com/flagship/targeting/operators/) for the full list of operators and configuration options.

## Evaluation context

The evaluation context is a set of key-value attributes that describe the current user or request (for example, `userId`, `country`, `plan`).

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

TypeScript

```

const value = await env.FLAGS.getBooleanValue("new-checkout", false, {

  userId: "user-42",

  country: "US",

});


```

When using the [OpenFeature SDK](https://developers.cloudflare.com/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.

## Flag propagation

During the brief propagation window after a flag change, some regions may still serve the previous flag value. After propagation completes, all subsequent evaluations return the updated value.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/concepts/","name":"Concepts"}}]}
```

---

---
title: Configuration
description: To use Flagship in a Cloudflare Worker, add a Flagship binding to your Wrangler configuration file. The binding gives your Worker access to env.FLAGS, which provides methods to evaluate feature flags.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/configuration.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Configuration

To use Flagship in a Cloudflare Worker, add a Flagship binding to your Wrangler configuration file. The binding gives your Worker access to `env.FLAGS`, which provides methods to evaluate feature flags.

## Add the binding

Add the `flagship` block to your Wrangler configuration file with a binding name and your app ID.

* [  wrangler.jsonc ](#tab-panel-6849)
* [  wrangler.toml ](#tab-panel-6850)

JSONC

```

{

  "flagship": {

    "binding": "FLAGS",

    "app_id": "<APP_ID>",

  },

}


```

TOML

```

[flagship]

binding = "FLAGS"

app_id = "<APP_ID>"


```

Replace `<APP_ID>` with the app ID from your Flagship app. If you have not created an app yet, refer to the [Get started guide](https://developers.cloudflare.com/flagship/get-started/#create-an-app-and-a-flag). The `binding` field sets the name you use to access Flagship in your Worker code (for example, `env.FLAGS`).

## Bind to multiple apps

A single Worker can bind to multiple Flagship apps. Use the array form to define more than one binding:

* [  wrangler.jsonc ](#tab-panel-6851)
* [  wrangler.toml ](#tab-panel-6852)

JSONC

```

{

  "flagship": [

    {

      "binding": "FLAGS",

      "app_id": "<APP_ID_1>",

    },

    {

      "binding": "EXPERIMENT_FLAGS",

      "app_id": "<APP_ID_2>",

    },

  ],

}


```

Explain Code

TOML

```

[[flagship]]

binding = "FLAGS"

app_id = "<APP_ID_1>"


[[flagship]]

binding = "EXPERIMENT_FLAGS"

app_id = "<APP_ID_2>"


```

Each binding is available as a separate property on the `env` object (for example, `env.FLAGS` and `env.EXPERIMENT_FLAGS`).

## Generate types

After adding the binding, run `npx wrangler types` to generate TypeScript types. This creates the `Env` interface with each binding typed as `Flagship`.

TypeScript

```

interface Env {

  FLAGS: Flagship;

  EXPERIMENT_FLAGS: Flagship;

}


```

## Use the binding

Call evaluation methods on `env.FLAGS` to resolve flag values at runtime. Each method accepts a flag key, a default value, and an optional evaluation context.

* [  JavaScript ](#tab-panel-6853)
* [  TypeScript ](#tab-panel-6854)

JavaScript

```

export default {

  async fetch(request, env) {

    const isEnabled = await env.FLAGS.getBooleanValue("my-feature", false, {

      userId: "user-42",

    });


    return new Response(isEnabled ? "Feature is on" : "Feature is off");

  },

};


```

TypeScript

```

export default {

  async fetch(request: Request, env: Env): Promise<Response> {

    const isEnabled = await env.FLAGS.getBooleanValue("my-feature", false, {

      userId: "user-42",

    });


    return new Response(isEnabled ? "Feature is on" : "Feature is off");

  },

};


```

Refer to the [binding API reference](https://developers.cloudflare.com/flagship/binding/) for the full list of methods.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/configuration/","name":"Configuration"}}]}
```

---

---
title: Binding API
description: Workers access Flagship through a binding that you add to your Wrangler configuration file. The binding field sets the variable name you use in your Worker code.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/binding/index.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Binding API

Workers access Flagship through a binding that you add to your Wrangler configuration file. The `binding` field sets the variable name you use in your Worker code.

* [  wrangler.jsonc ](#tab-panel-6845)
* [  wrangler.toml ](#tab-panel-6846)

JSONC

```

{

  "flagship": {

    "binding": "FLAGS",

    "app_id": "<APP_ID>",

  },

}


```

TOML

```

[flagship]

binding = "FLAGS"

app_id = "<APP_ID>"


```

Replace `<APP_ID>` with the app ID from your Flagship app. If you have not created an app yet, refer to the [Get started guide](https://developers.cloudflare.com/flagship/get-started/#create-an-app-and-a-flag). With this configuration, the binding is available as `env.FLAGS`. Refer to [Configuration](https://developers.cloudflare.com/flagship/configuration/) for additional options such as binding to multiple apps.

The binding provides type-safe methods for evaluating feature flags. If an evaluation fails or a flag is not found, the method returns the default value you provide.

* [  JavaScript ](#tab-panel-6847)
* [  TypeScript ](#tab-panel-6848)

JavaScript

```

export default {

  async fetch(request, env) {

    const enabled = await env.FLAGS.getBooleanValue("new-feature", false, {

      userId: "user-42",

    });

    return new Response(enabled ? "Feature on" : "Feature off");

  },

};


```

TypeScript

```

export default {

  async fetch(request: Request, env: Env): Promise<Response> {

    const enabled = await env.FLAGS.getBooleanValue("new-feature", false, {

      userId: "user-42",

    });

    return new Response(enabled ? "Feature on" : "Feature off");

  },

};


```

The binding has the type `Flagship` from the `@cloudflare/workers-types` package.

* [ Types ](https://developers.cloudflare.com/flagship/binding/types/)
* [ Methods ](https://developers.cloudflare.com/flagship/binding/methods/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/binding/","name":"Binding API"}}]}
```

---

---
title: Methods
description: The Flagship binding provides the following methods for evaluating feature flags. All methods are asynchronous and return a Promise. Evaluation methods never throw — they always return a value, falling back to the defaultValue you provide on errors.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/binding/methods.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Methods

The Flagship binding provides the following methods for evaluating feature flags. All methods are asynchronous and return a `Promise`. Evaluation methods never throw — they always return a value, falling back to the `defaultValue` you provide on errors.

Refer to the [types reference](https://developers.cloudflare.com/flagship/binding/types/) for the definitions of `FlagshipEvaluationContext` and `FlagshipEvaluationDetails`.

## `get()`

Returns the raw flag value without type checking. Use this method when the flag type is not known at compile time.

TypeScript

```

get(flagKey: string, defaultValue?: unknown, context?: FlagshipEvaluationContext): Promise<unknown>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | unknown                   | No       | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

const value = await env.FLAGS.get("checkout-flow", "v1", {

  userId: "user-42",

});


```

## `getBooleanValue()`

Returns the flag value as a `boolean`.

TypeScript

```

getBooleanValue(flagKey: string, defaultValue: boolean, context?: FlagshipEvaluationContext): Promise<boolean>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | boolean                   | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

const enabled = await env.FLAGS.getBooleanValue("dark-mode", false, {

  userId: "user-42",

});


```

## `getStringValue()`

Returns the flag value as a `string`.

TypeScript

```

getStringValue(flagKey: string, defaultValue: string, context?: FlagshipEvaluationContext): Promise<string>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | string                    | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

const variant = await env.FLAGS.getStringValue("checkout-flow", "v1", {

  userId: "user-42",

  country: "US",

});


```

## `getNumberValue()`

Returns the flag value as a `number`.

TypeScript

```

getNumberValue(flagKey: string, defaultValue: number, context?: FlagshipEvaluationContext): Promise<number>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | number                    | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

const maxRetries = await env.FLAGS.getNumberValue("max-retries", 3, {

  plan: "enterprise",

});


```

## `getObjectValue()`

Returns the flag value as a typed object. Use the generic parameter `T` to specify the expected shape.

TypeScript

```

getObjectValue<T extends object>(flagKey: string, defaultValue: T, context?: FlagshipEvaluationContext): Promise<T>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | T                         | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

interface ThemeConfig {

  primaryColor: string;

  fontSize: number;

}


const theme = await env.FLAGS.getObjectValue<ThemeConfig>(

  "theme-config",

  { primaryColor: "#000", fontSize: 14 },

  { userId: "user-42" },

);


```

Explain Code

## `getBooleanDetails()`

Returns the flag value as a `boolean` with evaluation metadata.

TypeScript

```

getBooleanDetails(flagKey: string, defaultValue: boolean, context?: FlagshipEvaluationContext): Promise<FlagshipEvaluationDetails<boolean>>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | boolean                   | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

const details = await env.FLAGS.getBooleanDetails("dark-mode", false, {

  userId: "user-42",

});

console.log(details.value); // true

console.log(details.reason); // "TARGETING_MATCH"


```

## `getStringDetails()`

Returns the flag value as a `string` with evaluation metadata.

TypeScript

```

getStringDetails(flagKey: string, defaultValue: string, context?: FlagshipEvaluationContext): Promise<FlagshipEvaluationDetails<string>>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | string                    | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

const details = await env.FLAGS.getStringDetails("checkout-flow", "v1", {

  userId: "user-42",

});

console.log(details.value); // "v2"

console.log(details.variant); // "new"

console.log(details.reason); // "TARGETING_MATCH"


```

## `getNumberDetails()`

Returns the flag value as a `number` with evaluation metadata.

TypeScript

```

getNumberDetails(flagKey: string, defaultValue: number, context?: FlagshipEvaluationContext): Promise<FlagshipEvaluationDetails<number>>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | number                    | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

const details = await env.FLAGS.getNumberDetails("max-retries", 3, {

  plan: "enterprise",

});

console.log(details.value); // 5

console.log(details.reason); // "TARGETING_MATCH"


```

## `getObjectDetails()`

Returns the flag value as a typed object with evaluation metadata. Use the generic parameter `T` to specify the expected shape.

TypeScript

```

getObjectDetails<T extends object>(flagKey: string, defaultValue: T, context?: FlagshipEvaluationContext): Promise<FlagshipEvaluationDetails<T>>


```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | T                         | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```

interface ThemeConfig {

  primaryColor: string;

  fontSize: number;

}


const details = await env.FLAGS.getObjectDetails<ThemeConfig>(

  "theme-config",

  { primaryColor: "#000", fontSize: 14 },

  { userId: "user-42" },

);

console.log(details.value); // { primaryColor: "#0051FF", fontSize: 16 }

console.log(details.variant); // "brand-refresh"


```

Explain Code

## Error handling

Evaluation methods never throw. They always return a value. When an error occurs, the method returns the `defaultValue` you provided. Use the `*Details` variants to inspect what went wrong.

### Type mismatch

If you call a typed method on a flag with a different type (for example, `getBooleanValue` on a string flag), the method returns the default value. The `*Details` variants set `errorCode` to `"TYPE_MISMATCH"`.

TypeScript

```

// Flag "checkout-flow" is a string flag, but you call getBooleanDetails.

const details = await env.FLAGS.getBooleanDetails("checkout-flow", false);

console.log(details.value); // false (the default value)

console.log(details.errorCode); // "TYPE_MISMATCH"


```

### Evaluation failure

If evaluation fails for any other reason (for example, a network error or missing flag), the method returns the default value. The `*Details` variants set `errorCode` to `"GENERAL"`.

TypeScript

```

const details = await env.FLAGS.getStringDetails(

  "nonexistent-flag",

  "fallback",

);

console.log(details.value); // "fallback"

console.log(details.errorCode); // "GENERAL"


```

## Parameters reference

The following table summarizes the parameters shared across all evaluation methods.

| Parameter    | Type                      | Required         | Description                                                                                   |
| ------------ | ------------------------- | ---------------- | --------------------------------------------------------------------------------------------- |
| flagKey      | string                    | Yes              | The key of the flag to evaluate.                                                              |
| defaultValue | varies                    | Yes (except get) | The fallback value returned if evaluation fails or the flag is not found.                     |
| context      | FlagshipEvaluationContext | No               | Key-value attributes for targeting rules (for example, { userId: "user-42", country: "US" }). |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/binding/","name":"Binding API"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/binding/methods/","name":"Methods"}}]}
```

---

---
title: Types
description: The Flagship binding uses the following TypeScript types. These are available from the @cloudflare/workers-types package after running npx wrangler types.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/binding/types.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Types

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

## `Flagship`

The binding type. Each Flagship binding in your Wrangler configuration is typed as `Flagship` on the `Env` interface.

TypeScript

```

interface Env {

  FLAGS: Flagship;

}


```

Refer to the [methods reference](https://developers.cloudflare.com/flagship/binding/methods/) for the full list of evaluation methods available on the binding.

## `FlagshipEvaluationContext`

A record of attribute names to values passed for [targeting rules](https://developers.cloudflare.com/flagship/targeting/). Use this to provide user attributes such as user ID, country, or plan type.

TypeScript

```

type FlagshipEvaluationContext = Record<string, string | number | boolean>;


```

## `FlagshipEvaluationDetails`

Returned by the `*Details` methods. Contains the evaluated value and metadata about how Flagship resolved the flag.

TypeScript

```

interface FlagshipEvaluationDetails<T> {

  flagKey: string;

  value: 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 variation, 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 human-readable description of the error.                                          |

Refer to [evaluation reasons and error codes](https://developers.cloudflare.com/flagship/reference/evaluation-reasons/) for the full list of possible values.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/binding/","name":"Binding API"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/binding/types/","name":"Types"}}]}
```

---

---
title: OpenFeature SDK
description: OpenFeature is the CNCF standard for feature flag interfaces. It provides a vendor-neutral API so you can switch between flag providers without changing evaluation code.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/sdk/index.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# OpenFeature SDK

Evaluate Flagship feature flags from any JavaScript runtime using OpenFeature.

[OpenFeature ↗](https://openfeature.dev/) is the CNCF standard for feature flag interfaces. It provides a vendor-neutral API so you can switch between flag providers without changing evaluation code.

The [@cloudflare/flagship ↗](https://www.npmjs.com/package/@cloudflare/flagship) package is an OpenFeature-compatible SDK for evaluating Flagship feature flags. The source code is available on [GitHub ↗](https://github.com/cloudflare/flagship).

The SDK includes two providers:

* **FlagshipServerProvider** — For server-side runtimes such as [Cloudflare Workers](https://developers.cloudflare.com/workers/), Node.js, and other server-side JavaScript environments. Each evaluation call makes an asynchronous request to the Flagship evaluation endpoint.
* **FlagshipClientProvider** — For browser applications. Pre-fetches all flag values on initialization and evaluates synchronously from an in-memory cache.

Note

If you are running inside a Cloudflare Worker, the [binding](https://developers.cloudflare.com/flagship/binding/) is the recommended approach because it avoids HTTP overhead. You can also [pass the binding to the OpenFeature SDK](https://developers.cloudflare.com/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.

## Installation

For server-side usage:

 npm  yarn  pnpm  bun 

```
npm i @cloudflare/flagship @openfeature/server-sdk
```

```
yarn add @cloudflare/flagship @openfeature/server-sdk
```

```
pnpm add @cloudflare/flagship @openfeature/server-sdk
```

```
bun add @cloudflare/flagship @openfeature/server-sdk
```

For browser usage:

 npm  yarn  pnpm  bun 

```
npm i @cloudflare/flagship @openfeature/web-sdk
```

```
yarn add @cloudflare/flagship @openfeature/web-sdk
```

```
pnpm add @cloudflare/flagship @openfeature/web-sdk
```

```
bun add @cloudflare/flagship @openfeature/web-sdk
```

## Next steps

* Set up the [server provider](https://developers.cloudflare.com/flagship/sdk/server-provider/) for Workers, Node.js, or other server-side runtimes.
* Set up the [client provider](https://developers.cloudflare.com/flagship/sdk/client-provider/) for browser applications.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/sdk/","name":"OpenFeature SDK"}}]}
```

---

---
title: Client provider
description: The FlagshipClientProvider implements the OpenFeature web provider interface for browser applications. It pre-fetches a declared set of flag values on initialization and resolves evaluations synchronously from an in-memory cache.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/sdk/client-provider.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Client provider

The `FlagshipClientProvider` implements the OpenFeature web provider interface for browser applications. It pre-fetches a declared set of flag values on initialization and resolves evaluations synchronously from an in-memory cache.

This makes the provider suitable for client-side rendering where synchronous access to flag values is required.

Important

The client provider requires an API token to fetch flag values. This token is not scoped to a single app, so anyone with the token can **evaluate flags** across all apps in your account. Use the client provider with caution in public-facing applications.

## prefetchFlags

`prefetchFlags` is a required array of flag keys that the provider fetches during initialization and on every context change. Only flags listed in this array are available for synchronous evaluation — any flag key not included returns a `FLAG_NOT_FOUND` error at resolution time.

**Fetch behavior:**

* **On initialization** — all flags in `prefetchFlags` are fetched in parallel and stored in an in-memory cache. The provider transitions to `READY` once all fetches complete (individual failures are non-fatal).
* **On context change** — the cache is invalidated and all flags are re-fetched for the new context. This is required by the [static context paradigm ↗](https://openfeature.dev/specification/glossary/#static-context-paradigm) used by the OpenFeature web SDK, where context is set globally and providers are expected to re-evaluate when it changes.
* **At resolution time** — evaluations are served synchronously from the cache. No network request is made during `getBooleanValue`, `getStringValue`, etc.

## Setup

The following example initializes the provider with a set of pre-fetched flags and evaluates them in a browser application.

* [  JavaScript ](#tab-panel-6867)
* [  TypeScript ](#tab-panel-6868)

JavaScript

```

import { OpenFeature } from "@openfeature/web-sdk";

import { FlagshipClientProvider } from "@cloudflare/flagship";


await OpenFeature.setProviderAndWait(

  new FlagshipClientProvider({

    appId: "<APP_ID>",

    accountId: "<ACCOUNT_ID>",

    authToken: "<API_TOKEN>",

    prefetchFlags: ["promo-banner", "dark-mode", "max-uploads"],

  }),

);


// Set evaluation context globally. The provider re-fetches all prefetchFlags

// whenever the context changes.

await OpenFeature.setContext({ targetingKey: "user-42", plan: "enterprise" });


const client = OpenFeature.getClient();


// Synchronous — served from the in-memory cache.

const showBanner = client.getBooleanValue("promo-banner", false);


if (showBanner) {

  document.getElementById("banner").style.display = "block";

}


```

Explain Code

TypeScript

```

import { OpenFeature } from "@openfeature/web-sdk";

import { FlagshipClientProvider } from "@cloudflare/flagship";


await OpenFeature.setProviderAndWait(

  new FlagshipClientProvider({

    appId: "<APP_ID>",

    accountId: "<ACCOUNT_ID>",

    authToken: "<API_TOKEN>",

    prefetchFlags: ["promo-banner", "dark-mode", "max-uploads"],

  }),

);


// Set evaluation context globally. The provider re-fetches all prefetchFlags

// whenever the context changes.

await OpenFeature.setContext({ targetingKey: "user-42", plan: "enterprise" });


const client = OpenFeature.getClient();


// Synchronous — served from the in-memory cache.

const showBanner = client.getBooleanValue("promo-banner", false);


if (showBanner) {

  document.getElementById("banner").style.display = "block";

}


```

Explain Code

Note

`getBooleanValue` on the client provider is synchronous and does not require `await`, unlike the [server provider](https://developers.cloudflare.com/flagship/sdk/server-provider/).

## Configuration options

| Option        | Type       | Required | Description                                                                                                                            |
| ------------- | ---------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| appId         | string     | Yes      | The Flagship app ID from the Cloudflare dashboard.                                                                                     |
| accountId     | string     | Yes      | Your Cloudflare account ID.                                                                                                            |
| authToken     | string     | Yes      | A Cloudflare [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with Flagship read permissions. |
| 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.   |

## When to use the client provider

Use the client provider in browser applications, single-page apps, or any client-side JavaScript environment.

Evaluations are synchronous, so they do not block rendering. Flag values are fetched once during initialization and re-fetched whenever the evaluation context changes. To force a refresh, update the context via `OpenFeature.setContext(...)`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/sdk/","name":"OpenFeature SDK"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/sdk/client-provider/","name":"Client provider"}}]}
```

---

---
title: Server provider
description: The FlagshipServerProvider implements the OpenFeature server provider interface. The provider works in Cloudflare Workers, Node.js, and any server-side JavaScript runtime that supports the Fetch API.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/sdk/server-provider.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Server provider

The `FlagshipServerProvider` implements the OpenFeature server provider interface. The provider works in [Cloudflare Workers](https://developers.cloudflare.com/workers/), Node.js, and any server-side JavaScript runtime that supports the Fetch API.

Inside a Cloudflare Worker, you can pass the Flagship [binding](https://developers.cloudflare.com/flagship/binding/) directly to the provider. This avoids HTTP overhead and is the recommended approach. Outside of Workers, initialize the provider with an app ID and account ID — each evaluation call makes an HTTP request to the Flagship evaluation endpoint.

## Setup

* [ With binding ](#tab-panel-6879)
* [ With app ID ](#tab-panel-6880)

Pass the Flagship binding directly to the provider. This is the recommended approach inside a Worker.

* [  JavaScript ](#tab-panel-6877)
* [  TypeScript ](#tab-panel-6878)

JavaScript

```

import { OpenFeature } from "@openfeature/server-sdk";

import { FlagshipServerProvider } from "@cloudflare/flagship";


export default {

  async fetch(request, env) {

    await OpenFeature.setProviderAndWait(

      new FlagshipServerProvider({ binding: env.FLAGS }),

    );


    const client = OpenFeature.getClient();


    const showNewCheckout = await client.getBooleanValue(

      "new-checkout",

      false,

      { targetingKey: "user-42", plan: "enterprise" },

    );


    if (showNewCheckout) {

      return new Response("New checkout enabled!");

    }


    return new Response("Standard checkout.");

  },

};


```

Explain Code

TypeScript

```

import { OpenFeature } from "@openfeature/server-sdk";

import { FlagshipServerProvider } from "@cloudflare/flagship";


export default {

  async fetch(request: Request, env: Env): Promise<Response> {

    await OpenFeature.setProviderAndWait(

      new FlagshipServerProvider({ binding: env.FLAGS }),

    );


    const client = OpenFeature.getClient();


    const showNewCheckout = await client.getBooleanValue(

      "new-checkout",

      false,

      { targetingKey: "user-42", plan: "enterprise" },

    );


    if (showNewCheckout) {

      return new Response("New checkout enabled!");

    }


    return new Response("Standard checkout.");

  },

};


```

Explain Code

Use an app ID, account ID, and an API token when running outside of a Worker (for example, in Node.js). The provider makes HTTP requests to the Flagship evaluation endpoint. Generate an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) from your Cloudflare account with Flagship read permissions.

* [  JavaScript ](#tab-panel-6873)
* [  TypeScript ](#tab-panel-6874)

JavaScript

```

import { OpenFeature } from "@openfeature/server-sdk";

import { FlagshipServerProvider } from "@cloudflare/flagship";


await OpenFeature.setProviderAndWait(

  new FlagshipServerProvider({

    appId: "<APP_ID>",

    accountId: "<ACCOUNT_ID>",

    authToken: "<API_TOKEN>",

  }),

);


const client = OpenFeature.getClient();


const showNewCheckout = await client.getBooleanValue("new-checkout", false, {

  targetingKey: "user-42",

  plan: "enterprise",

});


```

Explain Code

TypeScript

```

import { OpenFeature } from "@openfeature/server-sdk";

import { FlagshipServerProvider } from "@cloudflare/flagship";


await OpenFeature.setProviderAndWait(

  new FlagshipServerProvider({

    appId: "<APP_ID>",

    accountId: "<ACCOUNT_ID>",

    authToken: "<API_TOKEN>",

  }),

);


const client = OpenFeature.getClient();


const showNewCheckout = await client.getBooleanValue("new-checkout", false, {

  targetingKey: "user-42",

  plan: "enterprise",

});


```

Explain Code

## Configuration options

| Option    | Type     | Required | Description                                                                                                                                                               |
| --------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| binding   | Flagship | No       | The Flagship binding from env.FLAGS. Use this inside a Worker for best performance. Authentication is handled automatically through the binding.                          |
| appId     | string   | No       | The Flagship app ID from the Cloudflare dashboard. Required when not using a binding.                                                                                     |
| accountId | string   | No       | Your Cloudflare account ID. Required when not using a binding.                                                                                                            |
| authToken | string   | No       | A Cloudflare [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with Flagship read permissions. Required when not using a binding. |

Provide either `binding` or `appId`, `accountId`, and `authToken`.

## Evaluation context

OpenFeature uses an evaluation context to pass user attributes to the flag provider. The `targetingKey` field is the primary user identifier.

Pass additional attributes alongside `targetingKey` to match [targeting rules](https://developers.cloudflare.com/flagship/targeting/). For example, you can include `plan`, `country`, or any custom attribute your rules reference.

* [  JavaScript ](#tab-panel-6869)
* [  TypeScript ](#tab-panel-6870)

JavaScript

```

const value = await client.getBooleanValue("new-checkout", false, {

  targetingKey: "user-42",

  plan: "enterprise",

  country: "US",

});


```

TypeScript

```

const value = await client.getBooleanValue("new-checkout", false, {

  targetingKey: "user-42",

  plan: "enterprise",

  country: "US",

});


```

## Available hooks

The SDK ships with two hooks that you can attach to the OpenFeature client.

* **LoggingHook** — Logs structured information for every evaluation.
* **TelemetryHook** — Captures timing and event data for observability.

* [  JavaScript ](#tab-panel-6871)
* [  TypeScript ](#tab-panel-6872)

JavaScript

```

import { LoggingHook, TelemetryHook } from "@cloudflare/flagship";


OpenFeature.addHooks(new LoggingHook(), new TelemetryHook());


```

TypeScript

```

import { LoggingHook, TelemetryHook } from "@cloudflare/flagship";


OpenFeature.addHooks(new LoggingHook(), new TelemetryHook());


```

## Migrate from another provider

If you use another OpenFeature-compatible provider (for example, LaunchDarkly or Flagsmith), switch to Flagship by replacing the provider initialization. No changes are needed at evaluation call sites.

* [  JavaScript ](#tab-panel-6875)
* [  TypeScript ](#tab-panel-6876)

JavaScript

```

// Before

await OpenFeature.setProviderAndWait(

  new LaunchDarklyProvider({ sdkKey: "..." }),

);


// After

await OpenFeature.setProviderAndWait(

  new FlagshipServerProvider({

    appId: "<APP_ID>",

    accountId: "<ACCOUNT_ID>",

    authToken: "<API_TOKEN>",

  }),

);


```

Explain Code

TypeScript

```

// Before

await OpenFeature.setProviderAndWait(

  new LaunchDarklyProvider({ sdkKey: "..." }),

);


// After

await OpenFeature.setProviderAndWait(

  new FlagshipServerProvider({

    appId: "<APP_ID>",

    accountId: "<ACCOUNT_ID>",

    authToken: "<API_TOKEN>",

  }),

);


```

Explain Code

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/sdk/","name":"OpenFeature SDK"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/sdk/server-provider/","name":"Server provider"}}]}
```

---

---
title: Targeting rules
description: Targeting rules let you serve different flag values to different users based on their attributes. Each flag can have zero or more rules.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/targeting/index.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Targeting rules

Targeting rules let you serve different flag values to different users based on their attributes. Each flag can have zero or more rules.

Rules are evaluated in sequential order, from top to bottom. The first rule whose conditions match is used, and its configured variation is returned. If no rule matches, Flagship returns the flag's default variation.

When a flag is disabled, the default variation is always returned regardless of rules.

## How rules work

A rule consists of:

* **Conditions** — One or more attribute comparisons that must be satisfied. For example, `country equals "US"` or `plan in ["enterprise", "business"]`.
* **Serve variation** — The variation to return when the rule matches.
* **Rollout** (optional) — A percentage-based gradual release. Only the specified percentage of matching users receive the rule's variation. The rest continue to the next rule.

## Condition structure

Each condition compares an attribute from the evaluation context against a value using an operator:

* **Attribute** — The context key to evaluate (for example, `userId`, `country`, `plan`).
* **Operator** — The comparison to perform. Flagship supports [11 operators](https://developers.cloudflare.com/flagship/targeting/operators/).
* **Value** — The value to compare against. Can be a string, number, or array depending on the operator.

## Logical grouping

Conditions within a rule can be grouped with `AND`/`OR` operators and nested up to six levels deep.

For example, to target enterprise users in the US or Canada:

* `AND`:  
   * `plan equals "enterprise"`  
   * `OR`:  
         * `country equals "US"`  
         * `country equals "CA"`

## Learn more

* [ Operators ](https://developers.cloudflare.com/flagship/targeting/operators/)
* [ Percentage rollouts ](https://developers.cloudflare.com/flagship/targeting/percentage-rollouts/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/targeting/","name":"Targeting rules"}}]}
```

---

---
title: Operators
description: Flagship supports 11 comparison operators for targeting rule conditions. Each operator compares an attribute from the evaluation context against a specified value.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/targeting/operators.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Operators

Flagship supports 11 comparison operators for targeting rule conditions. Each operator compares an attribute from the [evaluation context](https://developers.cloudflare.com/flagship/concepts/#evaluation-context) against a specified value.

## Operator reference

| Operator                  | Description                                                                          | Example                                                 | Value type                |
| ------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------- | ------------------------- |
| equals                    | Returns true if the attribute value matches the specified value.                     | country equals "US"                                     | String                    |
| not\_equals               | Returns true if the attribute value does not match the specified value.              | plan not\_equals "free"                                 | String                    |
| greater\_than             | Returns true if the attribute value is greater than the specified value.             | age greater\_than 18                                    | Number, ISO 8601 datetime |
| less\_than                | Returns true if the attribute value is less than the specified value.                | loginCount less\_than 5                                 | Number, ISO 8601 datetime |
| greater\_than\_or\_equals | Returns true if the attribute value is greater than or equal to the specified value. | score greater\_than\_or\_equals 90                      | Number, ISO 8601 datetime |
| less\_than\_or\_equals    | Returns true if the attribute value is less than or equal to the specified value.    | createdAt less\_than\_or\_equals "2025-01-01T00:00:00Z" | Number, ISO 8601 datetime |
| contains                  | Returns true if the attribute value contains the specified substring.                | email contains "@cloudflare.com"                        | String                    |
| starts\_with              | Returns true if the attribute value starts with the specified prefix.                | path starts\_with "/api/v2"                             | String                    |
| ends\_with                | Returns true if the attribute value ends with the specified suffix.                  | domain ends\_with ".dev"                                | String                    |
| in                        | Returns true if the attribute value is in the specified array.                       | country in \["US", "CA", "UK"\]                         | Array                     |
| not\_in                   | Returns true if the attribute value is not in the specified array.                   | userId not\_in \["blocked-1", "blocked-2"\]             | Array                     |

## Operator categories

### Equality operators

`equals`, `not_equals`

Use these operators for exact string matching. The comparison is case-sensitive.

### Comparison operators

`greater_than`, `less_than`, `greater_than_or_equals`, `less_than_or_equals`

These operators work with numeric values and ISO 8601 datetime strings. When comparing datetimes, provide the value in ISO 8601 format (for example, `"2025-01-01T00:00:00Z"`).

### String operators

`contains`, `starts_with`, `ends_with`

These operators perform substring matching against the attribute value. All string comparisons are case-sensitive.

### Array operators

`in`, `not_in`

The value must be an array. Flagship checks whether the attribute value is a member of the specified array.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/targeting/","name":"Targeting rules"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/targeting/operators/","name":"Operators"}}]}
```

---

---
title: Percentage rollouts
description: Percentage rollouts let you gradually release a feature to a fraction of your users. Any targeting rule can include a rollout percentage between 0 and 100.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/targeting/percentage-rollouts.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Percentage rollouts

Percentage rollouts let you gradually release a feature to a fraction of your users. Any [targeting rule](https://developers.cloudflare.com/flagship/targeting/) can include a rollout percentage between 0 and 100.

## How percentage rollouts work

When a rule has a percentage rollout, Flagship evaluates the rule's conditions first. If the conditions match, only the specified percentage of users receive the rule's variation. Users who do not fall into the rollout percentage continue to the next rule or receive the default variation if no further rules match.

## Sticky bucketing

Flagship uses consistent hashing on a configurable attribute to assign users to a rollout bucket. The same user always receives the same flag value for a given rollout configuration. This ensures a consistent experience across repeated evaluations.

By default, the bucketing attribute is `targetingKey`. You can configure which attribute to use for bucketing when you set up the rollout in the dashboard.

Random assignment without targetingKey

If `targetingKey` is not present in the evaluation context and no alternative bucketing attribute is configured, Flagship cannot produce a stable hash. In this case the rollout bucket is assigned randomly on each evaluation, meaning the same user may receive different flag values across requests.

Always provide a stable `targetingKey` (or configure a consistent bucketing attribute) to guarantee sticky bucketing.

## Example

Consider a flag `new-checkout` with the following rules:

1. **Rule 1**: `plan equals "enterprise"` — serve variation `on`.
2. **Rule 2**: 25% rollout on `userId` — serve variation `on`.
3. **Default variation**: `off`.

In this configuration:

* All enterprise users see the new checkout.
* 25% of all other users, determined by their `userId`, also see the new checkout.
* The remaining 75% of non-enterprise users see the standard checkout.

As you gain confidence, increase the rollout percentage until you reach 100%.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/targeting/","name":"Targeting rules"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/targeting/percentage-rollouts/","name":"Percentage rollouts"}}]}
```

---

---
title: Evaluation reasons and error codes
description: When you evaluate a flag using the binding's *Details methods or the OpenFeature SDK, the response includes a reason field that explains why a particular value was returned. If an error occurs, the response includes an errorCode field.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/reference/evaluation-reasons.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Evaluation reasons and error codes

When you evaluate a flag using the binding's `*Details` methods or the OpenFeature SDK, the response includes a `reason` field that explains why a particular value was returned. If an error occurs, the response includes an `errorCode` field.

## Evaluation reasons

| Reason           | Description                                                                                                                        |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| TARGETING\_MATCH | A targeting rule's conditions matched the evaluation context, and the rule's variation was returned.                               |
| SPLIT            | A targeting rule with a percentage rollout matched. The user fell within the rollout percentage and received the rule's variation. |
| DEFAULT          | No targeting rule matched the evaluation context. The flag's default variation was returned.                                       |
| DISABLED         | The flag is disabled. The default variation was returned regardless of targeting rules.                                            |

## Error codes

When an evaluation error occurs, the method returns the default value you provided. The `*Details` methods include additional metadata about the error.

| Error code       | Description                                                                                                                                                             |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| TYPE\_MISMATCH   | The flag's variation type does not match the requested type. For example, calling getBooleanValue on a flag whose variation is a string. The default value is returned. |
| GENERAL          | An unexpected error occurred during evaluation (for example, a network failure). The default value is returned.                                                         |
| FLAG\_NOT\_FOUND | The specified flag key does not exist in the app. The default value is returned.                                                                                        |

## Example

The following example inspects evaluation details returned by `getBooleanDetails`:

* [  JavaScript ](#tab-panel-6865)
* [  TypeScript ](#tab-panel-6866)

JavaScript

```

const details = await env.FLAGS.getBooleanDetails("my-feature", false, {

  userId: "user-42",

});


switch (details.reason) {

  case "TARGETING_MATCH":

    console.log(`Matched targeting rule, variant: ${details.variant}`);

    break;

  case "SPLIT":

    console.log(`Included in rollout, variant: ${details.variant}`);

    break;

  case "DEFAULT":

    console.log("No rule matched, using default variation");

    break;

  case "DISABLED":

    console.log("Flag is disabled");

    break;

}


if (details.errorCode) {

  console.error(

    `Evaluation error: ${details.errorCode} - ${details.errorMessage}`,

  );

}


```

Explain Code

TypeScript

```

const details = await env.FLAGS.getBooleanDetails("my-feature", false, {

  userId: "user-42",

});


switch (details.reason) {

  case "TARGETING_MATCH":

    console.log(`Matched targeting rule, variant: ${details.variant}`);

    break;

  case "SPLIT":

    console.log(`Included in rollout, variant: ${details.variant}`);

    break;

  case "DEFAULT":

    console.log("No rule matched, using default variation");

    break;

  case "DISABLED":

    console.log("Flag is disabled");

    break;

}


if (details.errorCode) {

  console.error(

    `Evaluation error: ${details.errorCode} - ${details.errorMessage}`,

  );

}


```

Explain Code

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/reference/evaluation-reasons/","name":"Evaluation reasons and error codes"}}]}
```

---

---
title: Limits
description: Flagship enforces the following limits.
image: https://developers.cloudflare.com/dev-products-preview.png
---

[Skip to content](#%5Ftop) 

Was this helpful?

YesNo

[ Edit page ](https://github.com/cloudflare/cloudflare-docs/edit/production/src/content/docs/flagship/reference/limits.mdx) [ Report issue ](https://github.com/cloudflare/cloudflare-docs/issues/new/choose) 

Copy page

# Limits

Flagship enforces the following limits.

## Platform limits

| Feature                         | Limit    |
| ------------------------------- | -------- |
| Apps per account                | 10,000   |
| Flags per app                   | 5,000    |
| Condition nesting depth         | 6 levels |
| 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.

## Notes

* Condition nesting depth counts from the top-level condition group. A flat list of conditions (no nesting) has a depth of 1.
* Flag configuration size refers to the total serialized size of all flags within a single app, including their variations and rules.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/reference/limits/","name":"Limits"}}]}
```
