OpenFeature

Use FastStats as an OpenFeature provider on the server or in the browser

OpenFeature is a vendor-neutral API for feature flags. @faststats/openfeature provides FastStats providers for its server and web SDKs, so you can read FastStats flags through the OpenFeature client you already use.

Already using @faststats/web or @faststats/react in the browser? The built-in SDK shares the visitor and session with analytics and records exposures only for flags you read.

Authentication

Both providers take a token: the project’s public token, or a FastStats API key scoped to the project with the featureFlagEvaluation:evaluate permission. Only use an API key on the server.

Server

npm install @openfeature/server-sdk @faststats/openfeature
import { FastStatsProvider } from "@faststats/openfeature/server";
import { OpenFeature } from "@openfeature/server-sdk";

await OpenFeature.setProviderAndWait(
	new FastStatsProvider({ token: process.env.FASTSTATS_FLAGS_TOKEN! }),
);

const client = OpenFeature.getClient();

const newCheckout = await client.getBooleanValue("new-checkout", false, {
	targetingKey: visitorId,
	userId: user?.id,
	userAgent: request.headers.get("user-agent") ?? undefined,
	plan: "pro",
});

Each evaluation is one request for that one flag, and is recorded as an exposure.

On the server, the flags service sees your server rather than the visitor. Pass userAgent so rules can match browser, os, and device, and set country yourself if your rules use it.

Web

npm install @openfeature/web-sdk @faststats/openfeature
import { FastStatsProvider } from "@faststats/openfeature/web";
import { OpenFeature } from "@openfeature/web-sdk";

await OpenFeature.setContext({ targetingKey: visitorId, plan: "pro" });
await OpenFeature.setProviderAndWait(
	new FastStatsProvider({
		token: "your_project_token",
		flags: ["new-checkout", "max-uploads"],
	}),
);

const client = OpenFeature.getClient();
const newCheckout = client.getBooleanValue("new-checkout", false);

Flags load once, and again whenever the context changes, then resolve from memory. Browser, OS, device, and country come from the visitor’s own request.

The web provider records every flag it loads as an exposure, whether or not the app reads it. List the keys your app uses in flags, or every flag in the project is loaded and counted.

Evaluation Context

Context fieldSent as
targetingKeyidentifier: a stable device or install ID. Required unless userId is set
userIdYour ID for a signed-in user. Rollouts bucket by it, so they follow the user
sessionIdLinks evaluations to a session in analytics
userAgentServer only: the visitor’s User-Agent, for browser, os, and device rules
anything elseAn attribute targeting rules can match on

Defaults and Errors

A flag resolves to the default passed at the call site when it does not exist, is archived, has a different type, or the service cannot be reached within timeoutMs. The evaluation details carry the matching OpenFeature error code.

const details = await client.getBooleanDetails("new-checkout", false, context);

details.variant; // "on"
details.reason; // OpenFeature reason, such as "TARGETING_MATCH"
details.flagMetadata.reason; // FastStats reason, such as "rule_match"
FastStats reasonOpenFeature reason
rule_matchTARGETING_MATCH
target_matchTARGETING_MATCH
fallthroughDEFAULT
disabledDISABLED
prerequisite_failedDISABLED

Options

OptionTypeDefaultDescription
tokenstringrequiredProject token or API key
endpointstringhttps://flags.faststats.devBase URL of the flags service
timeoutMsnumber3000Aborts a slower request
flagsstring[]all flagsWeb only: the flag keys to load
fetchtypeof fetchglobal fetchA fetch implementation to use instead