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.