Skip to content

Feature flags

vb.flags connects to the realtime flag stream and serves up flag values without an extra HTTP round-trip per evaluation. Pairs with the Feature flags concept page.

await vb.flags.connect({
context: {
userId: currentUser.id,
email: currentUser.email,
plan: currentUser.plan,
// any custom dims you target on
},
});

connect():

  1. Bulk-evaluates every flag against your context (POST /api/v1/flags/evaluate)
  2. Opens a WS to the __flags topic so updates push immediately
  3. Caches values in memory keyed by flag.key
  4. Falls back to bulk-eval polling if WS fails

After connect, every read is synchronous (cache hit):

vb.flags.isEnabled("new-checkout"); // → boolean
vb.flags.getString("homepage-variant", "A"); // → "A" | "B" | "C"
vb.flags.getNumber("max-uploads", 5);
vb.flags.getJson("rollout-config", { steps: [] });
vb.flags.all(); // → Map<string, FlagValue>

The second arg is a default — returned when the flag is missing or the client isn’t connected yet.

When the user logs in / out / changes plan:

await vb.flags.setContext({ userId: newUser.id, plan: "paid" });
// → re-bulks-evaluates and notifies subscribers
const off = vb.flags.on("change", (key, value) => {
console.log("flag changed", key, value);
});
// off() to unsubscribe

Per-flag listeners avoid wide re-renders in React UIs.

import { useFlag, useFlagString, useFlagNumber, useFlagJson } from "@vaultbase/sdk/flags/react";
function CheckoutButton() {
const isNew = useFlag("new-checkout", false);
return isNew ? <NewCheckout /> : <OldCheckout />;
}
function Banner() {
const variant = useFlagString("homepage-variant", "A");
return <div className={`banner-${variant}`}></div>;
}

The hook subscribes to vb.flags.on("change", ...) and re-renders on relevant updates only — no global ref-equality dance.

For apps already on the OpenFeature standard:

import { OpenFeature } from "@openfeature/web-sdk";
import { VaultbaseFlagsProvider } from "@vaultbase/sdk/openfeature";
OpenFeature.setProvider(new VaultbaseFlagsProvider(vb.flags));
const client = OpenFeature.getClient();
const enabled = await client.getBooleanValue("new-checkout", false);

Targeting context flows through OpenFeature’s targetingKey → Vaultbase’s userId.

vb.flags.disconnect(); // closes the WS, drops the cache

Don’t disconnect on every component unmount — vb.flags is a singleton on the client.

Run vb-flags to generate a TypeScript module from the live admin’s flag definitions:

Terminal window
bunx vb-flags --url https://admin.example.com --token $ADMIN_TOKEN > src/flags.gen.ts

The output augments the SDK’s types so flag reads become typed:

import "./flags.gen"; // module augmentation; importing once is enough
vb.flags.isEnabled("new-checkout"); // ✓ — known key
vb.flags.isEnabled("typo-key"); // ✗ — TS error
vb.flags.getString("homepage-variant", "A");
// ↑ literal union of declared variations

See Codegen + migrate CLI for the full CLI reference.