Skip to main content

JavaScript — Superposition OpenFeature Provider

The JavaScript provider is an OpenFeature-compatible provider for Superposition that runs in Node.js. It offers two provider variants:

  • LocalResolutionProvider — Fetches config from a data source (HTTP server), caches it locally, and evaluates flags in-process. Supports polling and on-demand refresh strategies. This is the recommended provider for most use cases.
  • SuperpositionAPIProvider — A stateless remote provider that makes an HTTP API call to the Superposition server on every evaluation. No local caching — useful for serverless or low-traffic scenarios.

npm: superposition-provider

Installation​

npm install @openfeature/server-sdk superposition-provider
note

You need a running Superposition server. See Quick Start for setup instructions.

Quick Start​

This is the most common usage — the provider connects to a Superposition server via HTTP, polls for config updates, and evaluates flags locally.

import { OpenFeature } from "@openfeature/server-sdk";
import {
LocalResolutionProvider,
HttpDataSource,
SuperpositionOptions,
} from "superposition-provider";

async function main() {
// 1. Create an HTTP data source pointing to your Superposition server
const httpSource = new HttpDataSource(
new SuperpositionOptions({
endpoint: "http://localhost:8080",
token: "your-api-token",
orgId: "localorg",
workspaceId: "test",
})
);

// 2. Create the provider with a polling refresh strategy
const provider = new LocalResolutionProvider({
dataSource: httpSource,
refreshStrategy: {
type: "polling",
interval: 60000, // milliseconds between polls
timeout: 30000, // HTTP request timeout in milliseconds
},
});

// 3. Register with OpenFeature and wait for initialization
await OpenFeature.setProviderAndWait(provider);
console.log("Provider initialized successfully");

// 4. Create a client
const client = OpenFeature.getClient();

// 5. Define evaluation context (dimensions)
const context = {
targetingKey: "user-42",
city: "Berlin",
os: "android",
};

// 6. Evaluate feature flags
const stringVal = await client.getStringValue("currency", "USD", context);
console.log("currency:", stringVal);

const numberVal = await client.getNumberValue("price", 0, context);
console.log("price:", numberVal);

const boolVal = await client.getBooleanValue("dark_mode", false, context);
console.log("dark_mode:", boolVal);

// 7. Cleanup
await OpenFeature.close();
}

main().catch(console.error);

Configuration Options​

SuperpositionOptions​

Connection options shared by HttpDataSource and SuperpositionAPIProvider:

FieldTypeRequiredDescription
endpointstringYesSuperposition server URL
tokenstringYesAuthentication token (bearer)
orgIdstringYesOrganisation ID
workspaceIdstringYesWorkspace ID
const options = new SuperpositionOptions({
endpoint: "http://localhost:8080",
token: "your-api-token",
orgId: "localorg",
workspaceId: "test",
});

Refresh Strategies​

// Polling — periodically fetches updates from the server
{
type: "polling",
interval: 60000, // milliseconds between polls (default: 60000)
timeout: 30000, // HTTP request timeout in milliseconds (default: 30000)
}

// On-Demand — fetches on first access, then caches with a TTL
{
type: "on-demand",
ttl: 300, // cache TTL in seconds (default: 300)
useStaleOnError: true, // serve stale data on fetch error (default: true)
timeout: 30000, // HTTP timeout in milliseconds (default: 30000)
}

ExperimentationOptions​

FieldTypeRequiredDescription
refreshStrategyRefreshStrategyYesHow experiment data is refreshed
evaluationCacheEvaluationCacheOptionsNoCache for experiment evaluations
defaultTossnumberNoDefault toss value for experiments
const experimentationOptions = {
refreshStrategy: {
type: "polling",
interval: 5000,
timeout: 2000,
},
evaluationCache: {
ttl: 300,
size: 1000,
},
defaultToss: 50,
};

EvaluationCacheOptions​

FieldTypeDefaultDescription
ttlnumber60Cache time-to-live in seconds
sizenumber500Maximum number of cache entries

Provider Variants​

Fetches config from a pluggable data source (HTTP), caches locally, and evaluates flags in-process. Accepts an optional fallback data source.

import {
LocalResolutionProvider,
HttpDataSource,
SuperpositionOptions,
} from "superposition-provider";

const httpSource = new HttpDataSource(
new SuperpositionOptions({
endpoint: "http://localhost:8080",
token: "token",
orgId: "localorg",
workspaceId: "dev",
})
);

const provider = new LocalResolutionProvider({
dataSource: httpSource,
refreshStrategy: {
type: "polling",
interval: 30000,
timeout: 10000,
},
experimentationOptions: {
refreshStrategy: {
type: "polling",
interval: 5000,
timeout: 2000,
},
evaluationCache: { ttl: 300, size: 1000 },
defaultToss: 50,
},
});

await OpenFeature.setProviderAndWait(provider);
const client = OpenFeature.getClient();

// Resolve all config at once (calls provider directly)
const context = { targetingKey: "user-1234", city: "Berlin", os: "android" };
const allConfig = await provider.resolveAllConfigDetails({}, context);
console.log("All config:", allConfig);

Key capabilities:

  • Pluggable data sources — use HttpDataSource for server-backed resolution
  • Optional fallback — provide a secondary data source that is used when the primary source fails
  • Full config resolution — resolve all features at once via resolveAllConfigDetails()

2. SuperpositionAPIProvider (Remote / Stateless)​

A stateless provider that calls the Superposition server on every evaluation. No local caching — each flag evaluation makes an HTTP request. Best for serverless, low-traffic, or scenarios where you always want the latest config.

import { OpenFeature } from "@openfeature/server-sdk";
import { SuperpositionAPIProvider, SuperpositionOptions } from "superposition-provider";

const provider = new SuperpositionAPIProvider(
new SuperpositionOptions({
endpoint: "http://localhost:8080",
token: "token",
orgId: "localorg",
workspaceId: "dev",
})
);

await OpenFeature.setProviderAndWait(provider);
const client = OpenFeature.getClient();

const context = { targetingKey: "user-42", city: "Berlin" };
const value = await client.getStringValue("currency", "USD", context);
console.log("currency:", value);

Evaluation Context​

const context = {
targetingKey: "user-42", // Used for experiment bucketing
city: "Berlin",
os: "ios",
customers: "platinum",
};

const value = await client.getStringValue("currency", "USD", context);
  • targetingKey — Used for experiment variant bucketing. Typically a user ID.
  • All other keys map to your Superposition dimensions.

Supported Value Types​

MethodReturn TypeDescription
getBooleanValuebooleanBoolean flag evaluation
getStringValuestringString flag evaluation
getNumberValuenumberNumber flag evaluation
getObjectValueobjectObject/JSON evaluation

The LocalResolutionProvider also supports resolving all features:

// Resolve all config at once
const allConfig = await provider.resolveAllConfigDetails({}, context);
tip

Use provider.resolveAllConfigDetails({}, context) to get the entire resolved configuration in one call. This calls the provider directly, bypassing the OpenFeature client.

ES Modules Setup​

Make sure your project uses ES modules. Add this to your package.json:

{
"type": "module"
}

Dependencies​

The JavaScript provider depends on:

  • @openfeature/server-sdk — OpenFeature Server SDK
  • superposition-sdk — Smithy-generated client for Superposition API
  • Native bindings for local config resolution (bundled)

Full Example​

See the integration test: clients/javascript/provider-sdk-tests/index.js