Flags and experiments
CLI commands to roll out feature flags and run A/B tests on paywalls and flags.
These commands create and roll out feature flags, fix them for one person, and run A/B tests from draft to a concluded winner. Studio's Feature flags and A/B tests pages do the same.
Feature flags and A/B tests are in early access. Ask us on Discord, or email support@voidhash.com on a paid plan, to turn them on for your team.
Feature flags
| Command | What it does | Key flags |
|---|---|---|
flag list | Flags with their state in production, whether test follows it, and their variants. | --archived |
flag view [flag] | Variants, and who gets the flag in production and in test. | |
flag create | Creates a flag, off unless you pass --rollout. | --key, --type boolean|string|number|json, --variant (repeat), --description, --rollout 10% |
flag enable [flag] | Turns a flag on. | --rollout, --env |
flag disable [flag] | Turns a flag off for everyone, overrides included. Asks first in production. | --env |
flag rollout [flag] [percent] | Sets the share of people no rule matches who get it. Lowering it in production asks first. | --env |
flag edit [flag] | Changes a flag's key or description. | --key, --description |
flag variants set [flag] [value…] | Sets exactly the values a flag hands out. Removing one asks first. | |
flag override [flag] [person] [setting] | Fixes a flag for one person: on, off, a variant, or clear. | --note, --env |
flag rule add [flag] [person…] | Adds a rule: who it matches, by name or by --when conditions, and the share of them who get the flag. | --when (repeat), --rollout, --variant, --name, --id, --first, --env |
flag rule remove [flag] [rule] | Removes a rule by its id or name. Asks first in production when the flag is on. | --env |
flag promote [flag] | Applies test's configuration to production, then test follows production. Asks first. | |
flag follow [flag] | Drops test's own configuration, so test follows production again. Asks first. | |
flag evaluate [person] | What a person gets from each flag, and why. | --flag (repeat), --env, --platform, --app-version, --os-version, --country, --locale |
flag archive [flag] | Archives a flag; apps stop receiving it. Asks first when it's on. | |
flag restore [flag] | Restores an archived flag as it was. |
Production and test
A flag decides separately in production and in test, which apps using a
test key read. Test follows production until you change something in it:
--env test on enable, disable, rollout, override or rule gives test a configuration of
its own, started from production's. Without --env, a command changes production.
voidhash flag enable new-onboarding --rollout 100% --env test # on for test builds only
voidhash flag override new-onboarding ada@example.com on --env test
voidhash flag promote new-onboarding # the same in productionflag promote copies test's switch, overrides, rules and share to production, and test follows
production again. flag follow drops test's configuration without changing production.
Rules
An environment is read top to bottom: its switch, then overrides, then rules in order, then the share everyone else gets. A rule says what share of the people it matches get the flag, and for a flag with variants which one. It matches the people it names one by one:
voidhash flag rule add new-checkout ada@example.com user_8231 --rollout 100% --name "Beta testers"
voidhash flag rule add new-checkout user_4411 --rollout 0% --first # never gets it
voidhash flag rollout new-checkout 0% # only the named people doand, with --when, everyone a condition holds for. Repeat --when and all of them must hold:
# Half of the people in Germany and Austria whose app is 2.4 or newer
voidhash flag rule add new-checkout --when 'country in DE,AT' --when 'app_version >= 2.4' --rollout 50%
# Everyone on the pro plan who opted into the beta, except on the web
voidhash flag rule add new-checkout --when 'trait:plan in pro' --when 'trait:beta is set' \
--when 'platform not in web' --rollout 100%A condition is <what> <how> [<values>], with values separated by commas:
| What | It reads |
|---|---|
trait:<key> | One of the person's traits, such as trait:plan. |
platform | ios, android or web. |
app_version, os_version | What the app reports, such as 2.4.1 and 17.4. |
country | The two-letter country the request comes from, such as DE. |
locale | The person's locale, such as en-US; en takes every region. |
| How | It holds when |
|---|---|
in, not in | The value is, or is not, one of the values, ignoring case. A missing value counts as not in. |
>=, < | The version or number is at least, or below, the one given: 2.10 is newer than 2.9. |
is set, is not set | There is, or is not, a value at all. |
A rule can name people and have conditions; it then matches either way. A new rule is read after
the ones before it; --first puts it first. flag view lists them in order, in words.
flag evaluate knows a person's traits but not their app, so a condition on the app counts as not
set unless you say what the app would report:
voidhash flag evaluate ada@example.com --platform ios --app-version 2.4.1 --country DEExperiments
| Command | What it does | Key flags |
|---|---|---|
experiment list | Experiments with their status and arms. | --status draft|running|paused|concluded, --archived |
experiment view [experiment] | Status, metric, the paywall each arm shows where and its flag values. | |
experiment create | Sets up a draft experiment. | --name, --hypothesis, --metric (set it, such as $subscription.created), --location, --arm, --flag, --control, --weights |
experiment edit [experiment] | Changes its setup. Metrics change only in a draft, arms not while running. | Same as create, plus --description, --secondary-metric |
experiment start [experiment] | Starts or resumes it at its locations and on its flags. Asks first. | |
experiment pause [experiment] | Pauses it: everyone sees the control arm. | |
experiment results [experiment] | Each arm's conversion, with a verdict that says when it's too early to tell. | |
experiment conclude [experiment] | Ends it for good with a winner. Shows the results and asks first. | --winner (default: the control) |
experiment archive [experiment] | Archives a draft or concluded experiment. | |
experiment restore [experiment] | Restores an archived experiment. |
Always pass --metric, the goal event. Without it, results count purchase_completed, an event
Voidhash never sends, so every arm shows 0 conversions. See Conversions
for which built-in event to use.
--arm takes NAME=PAYWALL with --location, or NAME=LOCATION:PAYWALL[,LOCATION:PAYWALL].
Repeat it for each arm; the first is the control unless --control names another, and
--weights 60,40 splits traffic unevenly.
--flag gives each arm a value for one of your feature flags, as KEY=VALUE,VALUE with one value
per --arm, in order. A value is on, off, or one of the flag's variant keys, which turns it on
with that variant. Repeat it for each flag. An arm needs no paywall then, so --arm NAME alone
tests a flag by itself:
voidhash experiment create --name "New checkout" --metric '$subscription.created' \
--arm Control --arm "New checkout" --flag new-checkout=off,onWhile the experiment runs, each flag takes the value of the person's arm, after the flag's switch
and overrides and before its rules. flag evaluate then says a running experiment set it. It only
looks: it doesn't put the person in an experiment.
Example
voidhash flag create --key new-onboarding --rollout 10%
voidhash experiment create --name "Annual first" --metric '$subscription.created' \
--location onboarding --arm Control=pro --arm Annual=annual-firstNext steps
- How a flag decides: environments, overrides, rules and rollouts.
- A/B test results: conversions and verdicts.
- Analytics and ads: measure the results.
Something wrong or missing on this page? Tell us by email or on Discord.