Cloudflare.Flagship reference
Source:
packages/cloudflare/src/Flagship/App.ts
A Cloudflare Flagship app — a container for feature flags.
Flagship is Cloudflare’s feature flag service. Flags are organized into
apps that map to your projects or services; the app’s appId is what a
Worker’s Flagship binding points at and what every evaluation call is
scoped to. The name is mutable in place; the app id never changes.
App: Creating an App
Section titled “App: Creating an App”App with a generated name
const app = yield* Cloudflare.Flagship.App("Flags", {});App with an explicit name
const app = yield* Cloudflare.Flagship.App("Flags", { name: "my-service-flags",});App: Using the App
Section titled “App: Using the App”const app = yield* Cloudflare.Flagship.App("Flags", {});
const flag = yield* Cloudflare.Flagship.Flag("NewCheckout", { appId: app.appId, key: "new-checkout", defaultVariation: "off", variations: { off: false, on: true },});App: Binding to a Worker
Section titled “App: Binding to a Worker”Effect-style Worker (recommended)
Cloudflare.Flagship.ReadFlags(app) attaches the binding to the surrounding
Worker and returns the runtime client for evaluating flags. Every Flagship
method is mirrored as an Effect, so no Effect.tryPromise wrapping is needed.
export const App = Cloudflare.Flagship.App("Flags", {});
Cloudflare.Worker( "FlagsWorker", { main: import.meta.url }, Effect.gen(function* () { const flags = yield* Cloudflare.Flagship.ReadFlags(App); return { fetch: Effect.gen(function* () { const enabled = yield* flags.getBooleanValue("new-checkout", false, { userId: "user-42", }); return HttpServerResponse.text(enabled ? "on" : "off"); }), }; }).pipe(Effect.provide(Cloudflare.Flagship.ReadFlagsBinding)),);Declare the binding on env
Declaring the app on a Worker’s env maps it to the native Flagship
runtime binding via InferEnv.
export const App = Cloudflare.Flagship.App("Flags", {});
export const Worker = Cloudflare.Worker("Worker", { main: "./src/worker.ts", env: { FLAGS: App },});
export type WorkerEnv = Cloudflare.InferEnv<typeof Worker>;// { FLAGS: Flagship }Async-style worker with the raw runtime binding
import type { WorkerEnv } from "../alchemy.run.ts";
export default { async fetch(request: Request, env: WorkerEnv) { const enabled = await env.FLAGS.getBooleanValue("new-checkout", false, { userId: "user-42", }); return new Response(enabled ? "on" : "off"); },};App: Local Development
Section titled “App: Local Development”Flags evaluate locally under alchemy dev
In alchemy dev the app and its flags are emulated on your machine: no
Cloudflare API calls, and the Worker’s binding evaluates flags locally with
the same targeting rules, rollouts, and evaluation reasons. Changing a flag
and saving applies to the running Worker without a restart.
const app = yield* Cloudflare.Flagship.App("Flags", {});
yield* Cloudflare.Flagship.Flag("NewCheckout", { appId: app.appId, key: "new-checkout", defaultVariation: "off", variations: { off: false, on: true }, rules: [ { priority: 1, conditions: [{ attribute: "country", operator: "equals", value: "US" }], serveVariation: "on", }, ],});
yield* Cloudflare.Worker("Worker", { main: "./src/worker.ts", env: { FLAGS: app },});Use the real app during alchemy dev
Pipe the app and its flags through Alchemy.remote() to create them on
Cloudflare; the local Worker’s binding then evaluates the live flags.
const app = yield* Cloudflare.Flagship.App("Flags", {}).pipe(Alchemy.remote());
yield* Cloudflare.Flagship.Flag("NewCheckout", { appId: app.appId, key: "new-checkout", defaultVariation: "off", variations: { off: false, on: true },}).pipe(Alchemy.remote());App: Looking up an existing app
Section titled “App: Looking up an existing app”App.lookup references an app Alchemy doesn’t manage (created in the
dashboard or by another stack), found by appId or name. It is read
during plan/deploy and never created, updated or deleted.
Cloudflare lists a new app about ten seconds after creating it, so a
lookup by name right after creation can miss it; appId never does.
const app = Cloudflare.Flagship.App.lookup({ name: "storefront" });yield* Cloudflare.Flagship.Flag("NewCheckout", { appId: app.appId, key: "new-checkout", defaultVariation: "off", variations: { off: false, on: true },});Source:
packages/cloudflare/src/Flagship/Flag.ts
A feature flag in a Cloudflare Flagship app.
A flag maps a key to a set of variations plus targeting rules. Workers
evaluate flags through the Flagship binding (or the REST evaluate
endpoint); changing variations, rules, enablement, or the default
variation takes effect without redeploying code. Everything except the
flag key and the parent app is mutable in place.
Flag: Creating a Flag
Section titled “Flag: Creating a Flag”Boolean flag
const app = yield* Cloudflare.Flagship.App("Flags", {});
const flag = yield* Cloudflare.Flagship.Flag("NewCheckout", { appId: app.appId, key: "new-checkout", defaultVariation: "off", variations: { off: false, on: true },});String flag with multiple variations
const flag = yield* Cloudflare.Flagship.Flag("CheckoutFlow", { appId: app.appId, key: "checkout-flow", defaultVariation: "v1", variations: { v1: "classic", v2: "express", v3: "one-click" },});Flag: Targeting Rules
Section titled “Flag: Targeting Rules”Serve a variation to a specific country
const flag = yield* Cloudflare.Flagship.Flag("DarkMode", { appId: app.appId, key: "dark-mode", defaultVariation: "off", variations: { off: false, on: true }, rules: [ { priority: 1, conditions: [ { attribute: "country", operator: "equals", value: "US" }, ], serveVariation: "on", }, ],});Percentage rollout
const flag = yield* Cloudflare.Flagship.Flag("NewSearch", { appId: app.appId, key: "new-search", defaultVariation: "off", variations: { off: false, on: true }, rules: [ { priority: 1, conditions: [], serveVariation: "on", rollout: { percentage: 25 }, }, ],});Flag: Toggling a Flag
Section titled “Flag: Toggling a Flag”const flag = yield* Cloudflare.Flagship.Flag("NewCheckout", { appId: app.appId, key: "new-checkout", enabled: false, defaultVariation: "off", variations: { off: false, on: true },});ReadFlags
Section titled “ReadFlags”Source:
packages/cloudflare/src/Flagship/ReadFlags.ts
Bind a App to a Worker and obtain the Effect-native flag-evaluation
client (get, getBooleanValue, getStringValue, …).
ReadFlags is a single identifier that is simultaneously the binding’s
Context tag, its type, and the callable —
yield* Cloudflare.Flagship.ReadFlags(app).
ReadFlags: Examples
Section titled “ReadFlags: Examples”const flags = yield* Cloudflare.Flagship.ReadFlags(MyApp);const enabled = yield* flags.getBooleanValue("new-checkout", false);