VoidhashDocs
DocumentationAPI reference
Dashboard
Get started
Introduction
Quickstart
Setup
Setup overview
Create a project
Environments
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
Record payments from other sources
API libraries
Node.js
PHP
Rust
Go
Resources
MCP server
Ad measurement
Meta ads
Migrate in observer mode
Delete a person's data
Swift SDK
Swift quickstart
Display a paywall
Make and restore purchases
Check access
Identify customers
Evaluate feature flags
Capture analytics
Track screens
Development purchase mode
Errors

Evaluate feature flags

Gate features with remotely evaluated flags and variants.

Feature flags let you turn features on or off, and pick variants, without shipping a new build. Voidhash evaluates every flag for the current person, so the same flag can resolve differently for different customers. Use flags for staged rollouts, experiments, and remote configuration.

Evaluate flags

Pass the keys you need. Pass nil instead to evaluate every flag in the project:

let flags = try await voidhash.getFeatureFlags(["new-onboarding", "pricing-test"])

let newOnboarding = flags.first { $0.key == "new-onboarding" }?.enabled == true
let pricing = flags.first { $0.key == "pricing-test" }

Each result carries the flag's key, whether it is enabled, and the variantKey of the variant the customer was assigned.

Read a variant's payload

A variant can carry a payload, such as a headline or a pricing configuration. payload is a JSONValue, or nil when the variant has none. Payloads are untyped JSON, so validate a payload before you use it:

let pricing = try await voidhash.getFeatureFlags(["pricing-test"]).first

if case .object(let config)? = pricing?.payload,
    case .number(let trialDays)? = config["trialDays"]
{
    showTrial(days: Int(trialDays))
} else {
    showTrial(days: 7) // Safe default
}

Payloads are cached with the rest of the flag, so they stay available offline.

Defaults and slow networks

Results are cached on the device, so a flag read answers at once and keeps the last evaluation while Voidhash is unreachable. Only a read with nothing cached waits for Voidhash, and for at most 2 seconds. Without an answer by then, a requested flag reads as its default, and the evaluation carries on in the background. Set the defaults and listen for the late evaluation when you configure the SDK:

var options = VoidhashOptions()
options.featureFlags.defaults = ["new-onboarding": false, "pricing-test": false]
options.featureFlags.maxWaitMilliseconds = 2000 // The default
options.featureFlags.onUpdate = { _, _ in
    Task { @MainActor in model.reloadFlags() }
}
Voidhash.configure(publishableKey: "vh_pk_…", options: options)

A flag you ask for by key reads as its defaults entry until it has an evaluated value, also when Voidhash does not know the flag. onUpdate is called with the evaluated keys and results whenever a new evaluation is stored for the signed-in customer, including one that arrives after an outage ends; read your flags again then.

Identity behavior

Flag results are scoped to the current person. When an anonymous customer signs in with identify(), the flags evaluated before sign-in keep answering until the customer's own evaluation replaces them, so features don't flip back to their defaults while Voidhash is unreachable or before it has evaluated the customer. Signing out, a reset, switching to another customer, or a sign-in Voidhash refuses clears them, so one customer never sees another customer's assignment.

Choose a safe default to use while flags are loading or unavailable. Do not use a feature flag to gate paid access. Use entitlement grants for that instead.

PreviousIdentify customersNextCapture analytics

On this page

Evaluate flagsRead a variant's payloadDefaults and slow networksIdentity behavior