JavaScript (server)
Checks Switchyard feature flags from server-side JavaScript: Node 20+, Deno, Bun and edge runtimes. No dependencies; it uses the standard fetch.
The client keeps the environment's flags in memory and evaluates them there, so checking a flag is a function call, not a network request. Changes arrive within about a second over a live-update stream, with polling as a safety net. If the server goes away, checks keep using the last flags received.
Use it in your app
import { SwitchyardClient } from 'switchyard-js';
const flags = new SwitchyardClient({
sdkKey: process.env.SWITCHYARD_SDK_KEY!, // the environment's SDK key
baseUrl: 'https://flags.example.com', // your Switchyard server
});
// Plain on/off
if (flags.isEnabled('maintenance-banner', false)) {
showBanner();
}
// Targeting rules and percentage rollouts need to know who's asking
const user = { key: 'user-42', attributes: { email: 'dev@acme.com', country: 'IN', plan: 'pro' } };
if (flags.isEnabled('new-checkout', user, false)) {
return renderNewCheckout();
}- The last argument is the default: returned before the first fetch completes, and for flags the server doesn't know (never created, archived, or misspelled). Pick what's safe if Switchyard is unreachable.
keyshould be stable for each user (a user ID, not a session ID): the same key always lands in the same part of a rollout.- Attribute values are compared exactly and case-sensitively. Send emails in lowercase.
Flags that serve more than on/off (text, numbers, JSON) have typed methods. Each returns the default for a flag of another type:
const color = flags.stringVariation('checkout-button', user, 'green');
const limit = flags.numberVariation('upload-limit-mb', user, 10);
const plan = flags.jsonVariation<{ seats: number }>('plan-config', user, { seats: 5 });Optional extras:
await flags.ready(2000); // wait up to 2 s for the first fetch (checks work before, with defaults)
flags.onChange((keys) => console.log('changed:', keys));
flags.status; // 'starting' | 'ready' | 'stale' | 'unauthorized' | 'closed'
flags.close(); // when shutting down: the open stream keeps Node running otherwiseOptions
| Option | Default | |
|---|---|---|
sdkKey |
required | The environment's SDK key |
baseUrl |
http://localhost:8080 |
The Switchyard server |
pollInterval |
30000 |
ms between checks while healthy (every 5 minutes while the stream is up) |
requestTimeout |
10000 |
ms per request |
maxBackoff |
300000 |
Longest wait between retries while the server is failing |
streaming |
true |
Hold a live-update stream open |
logger |
console |
Where warnings go; null to silence |
fetch |
global fetch |
Your own, e.g. for a proxy |
Not for browsers. The SDK key can read every flag's rules (including, say, the email addresses a rule lists), so keep it on your servers.
OpenFeature
switchyard-js/openfeature is an OpenFeature provider, for code written against the vendor-neutral OpenFeature API. Install @openfeature/server-sdk alongside:
import { OpenFeature } from '@openfeature/server-sdk';
import { SwitchyardProvider } from 'switchyard-js/openfeature';
await OpenFeature.setProviderAndWait(new SwitchyardProvider({ sdkKey, baseUrl: 'https://flags.example.com' }));
const flags = OpenFeature.getClient();
const color = await flags.getStringValue('checkout-button', 'green', { targetingKey: userId, plan: 'pro' });The targetingKey is the context key; other context values become attributes (numbers, booleans and dates as text). Reasons map to OpenFeature's: TARGETING_MATCH (a rule; its index is in the flag metadata), DEFAULT (everyone else), DISABLED (off), plus PREREQUISITE_FAILED. Unknown flags and the wrong type give your default with FLAG_NOT_FOUND or TYPE_MISMATCH. Flag changes are sent on as PROVIDER_CONFIGURATION_CHANGED events.
evaluateDetail gives the same reasons without OpenFeature.
Same answers as every other client
Evaluation follows spec/EVALUATION.md and passes the shared evaluation vectors, so a user gets the same result here as in the Java client.
Develop
npm install
npm test # node --test, including the shared vectors
npm run typecheck
npm run build # ESM + type definitions in dist/
npm run bench # how long a flag check takesNode 24 runs the TypeScript sources directly, so the tests need no build step.