Feature flags#
Feature flags control how the app works in different environments and for different users.
Concepts#
Status#
The status of a feature can be one of three values:
enabled
disabled
switchable
This is configurable and must be set in the feature flags configuration file,
~/feat/feature-flags.json
.
A switchable
flag in a public environment like ‘staging’ or ‘production’
effectively becomes a user-level preferences toggle.
State#
The state of a feature can be one of two values:
on
off
This is determined by the feature status and user-preferences.
An
enabled
feature is alwayson
.A
disabled
feature is alwaysoff
.A switchable feature can be
on
oroff
based on the user’s preference. ThispreferredState
is recorded in a cookie. If no preference has been set, thedefaultState
will be used.
Cascade#
The current environment can be ‘local’, ‘development’, ‘staging’ or ‘production’
based on the DEPLOYMENT_ENV
environment variable (assumed ‘local’ by default).
If a feature status is set for an environment, it is assumed to be same value
for all environments before it and disabled
for all environments after it
(unless specified otherwise). For example, consider the following configuration:
{
"local": "enabled",
"staging": "switchable"
}
Here the feature will be
enabled
for ‘local’ environment (configured)switchable
for ‘development’ environment (cascaded from staging)switchable
for ‘staging’ environment (configured)disabled
for ‘production’ environment (default)
File structure#
The feature flags configuration file, ~/feat/feature-flags.json
contains two
top-level keys, features
and groups
.
features
#
This is a mapping of feature names to feature configurations.
Key: title#
This is an identifier for the feature. This identifier is looked up in the i18n
strings to generate a human-readable purpose (pref-page.features.${title}
) for
the feature.
Conventionally, _
is used as the separator for the name so that the name is a
valid JS identifier.
Value: configuration#
This controls the behavior of the feature flag. It is an object containing three
fields, status
, description
and defaultState
.
status
#
It is a mapping of different environments with the status of the flag in that environment. For example, a feature that’s in development may be ‘switchable’ in ‘staging’ but ‘disabled’ in ‘production’.
defaultState
#
This is the state of a switchable feature when the user has not switched it. For example, a feature that’s in development may start as ‘opt-in’, being ‘off’ by default and may gradually change to opt-out, becoming ‘on’ by default.
description
#
This is a description of the feature that appears in the internal /preferences
page.
⚠️ This field is not internationalised because it’s for internal use only. You
should populate en.json5
if the feature is switchable and
visible to the user.
storage
#
This determines whether the feature is stored in a cookie ('cookie'
) or in
sessionStorage
('session'
). By default all feature flags are stored in
cookies but certain preferences that should only be applicable for a single
session can be stored in sessionStorage
instead.
supportsQuery
#
By default, all switchable flags can be set per-request using the ff_<flag>
query parameters. This is useful for testing and debugging. However, some flags
dealing with sensitivity can be used to make malicious URLs, so they can avoid
being set via query parameters by setting this to false
.
groups
#
This setting pertains to how feature flags can serve as user-level preferences.
It is an array of objects, each containing two fields, title
and features
.
title
#
This is an identifier for the group. This identifier is looked up in the i18n
strings to generate a human-readable name (pref-page.groups.${title}.title
)
and description (pref-page.groups.${title}.desc
) for the group.
features
#
This is a list of strings where each string must be a
key from the upper features
section. Each switchable feature
from this list will show up in the preferences modal.