VoidhashDocs
DocumentationAPI reference
Dashboard
Get started
Introduction
Quickstart
Setup
Setup overview
Create a project
Products and perks
Paywall locations
CLI
Paywall components
Components
Develop a component
Editor panels
Component definition
Publishing
Installing and capabilities
SDKs
Swift
Kotlin
React Native
Web
Store setup
Connect the App Store
Connect Google Play
Connect Stripe
API libraries
Node.js
PHP
Rust
Go
Resources
MCP server
Meta ads
Migrate in observer mode
Delete a person's data
Web SDK
Web quickstart
Identify users
Track events
Page views and attribution
Stripe revenue
Web-to-app handoff
First-party proxy
Feature flags
Troubleshooting

Feature flags

Evaluate remotely configured flags and variants for the current visitor.

Feature flags turn features on or off, and pick variants, without a new deploy. Voidhash evaluates every flag for the current visitor, so the same flag can resolve differently for different people. Configure flags in Studio under Feature flags.

Evaluate flags

getFeatureFlags evaluates the keys you pass, or every flag when you pass none:

const { flags, isStale } = await voidhash.getFeatureFlags(["new-pricing", "checkout-test"]);
const newPricing = flags.find((flag) => flag.key === "new-pricing")?.enabled ?? false;

Each entry has key, enabled, and variantKey, which is null for a flag without variants. payload is always null in the web SDK; flag payloads are not delivered to browsers yet.

After an evaluation, read single flags synchronously:

const enabled = voidhash.isFeatureEnabled("new-pricing");
const variant = voidhash.getFeatureVariant("checkout-test")?.variantKey;

Unknown flags, and flags not evaluated yet, are disabled.

In React

useFeatureFlags evaluates the keys you pass and re-renders when they change. It compares keys by value, in any order, so it evaluates again only when the set of keys changes:

import { useFeatureFlags } from "@voidhash/web/react";

const FLAG_KEYS = ["new-pricing", "checkout-test"];

export function Pricing() {
  const { getVariant, isEnabled, isLoading } = useFeatureFlags(FLAG_KEYS);
  if (isLoading) return null;

  const checkout = getVariant("checkout-test");
  return (
    <PricingTable
      layout={isEnabled("new-pricing") ? "new" : "classic"}
      checkoutVariant={checkout?.variantKey ?? undefined}
    />
  );
}
ValuePurpose
data.flagsEvery evaluated entry.
isEnabled(key)Whether the flag is enabled. Unknown and still-loading flags return false.
getVariant(key)The flag's entry, or null while it is loading or unknown.
isLoadingtrue until the first evaluation answers, including while the provider starts; false when the client failed to start.
isStale, isExpiredtrue when the values came from the cache without a successful refresh.
errorThe error, when there was nothing to answer with or the client failed to start, or null.
refetch()Evaluates again from the network.

Caching and refresh

Flags are read from the cache first, so a cached value never waits for the network:

  • Fresh values are answered from the cache. Values older than featureFlags.ttlMs, five minutes by default, are refreshed; the read waits at most 500 ms for the refresh, then answers from the cache with isStale: true.
  • Without any cached value, the first read waits for Voidhash, at most 10 seconds, and then answers with every flag disabled.
  • The cache is kept in localStorage, so the next page load starts with the last values. Turn this off with featureFlags: { persist: false }, which keeps flags in memory for the page.
  • Flags are refreshed when the browser reconnects and when the tab becomes visible, at most once a minute.
  • identify(), signOut(), and reset() clear the cached flags and evaluate them again for the new person, so one visitor never sees another visitor's assignment.

Feature flags keep working while analytics consent is not granted.

Experiments

A flag with variants assigns each visitor a stable variant, which you can use for an A/B test on your website. The web SDK does not record an exposure event when a flag is read; to analyze a test, track an event of your own with the variant when the visitor sees it.

Choose a safe default for a flag that is loading or unavailable. Do not use a feature flag to gate paid access; check access on your server with the Node.js library.

PreviousFirst-party proxyNextTroubleshooting

On this page

Evaluate flagsIn ReactCaching and refreshExperiments