README
View SourceSimpleFeatureFlags provides basic, simple feature flag functionality. You can use application configuration (config/runtime.exs) to select the deployment environments in which a feature is enabled
This approach is useful when you want to roll out a feature to only a subset of your environments. Here are a couple of examples:
- You want to try a feature in your localhost and staging environments, before rolling it out to production.
- You want to use a feature in a subset of your production environments (based on a region, or some other grouping).
The example below describes switching to a new, exciting algorithm (:new_algorithm) for computing 𝝿 in :localhost and :staging deployment environments, before rolling it out to :production (or not).
Installation
The package can be installed by adding simple_feature_flags to your list of dependencies in mix.exs:
def deps do
[
{:simple_feature_flags, "~> 0.1"}
]
endThe docs can be found at https://hexdocs.pm/simple_feature_flags.
Configuration
Determine the name of the deployment environment you are running in, and list the environments in which your feature is enabled.
In this example, the name of the deployment environment is loaded from an environment variable, and the new_algorithm feature is enabled in localhost and staging:
config/runtime.exs
current_deployment_environment =
System.get_env("DEPLOYMENT_ENVIRONMENT")
|> case do
nil -> raise "DEPLOYMENT_ENVIRONMENT is not defined"
env -> String.to_atom(env)
end
config :simple_feature_flags, :flags, %{
current_deployment_environment: current_deployment_environment,
features: %{
new_algorithm: %{enabled_in: [:localhost, :staging]},
new_ui: %{enabled_in: [:staging]}
}
}Using Feature Flag in Your Code
Wrap your feature logic in SimpleFeatureFlags.enabled?/1:
defmodule MyApp.Pi do
def compute_pi() do
if SimpleFeatureFlags.enabled?(:new_algorithm) do
# Use the new, exciting algorithm.
compute_pi_new_algorithm()
else
# Use the old, boring algorithm.
3.14
end
end
endOptional: Log Configuration on Startup
lib/myapp/application.ex
defmodule MyApp.Application do
require Logger
use Application
@impl true
def start(_type, _args) do
Logger.info(SimpleFeatureFlags.current_configuration_to_string())
...Here is an example of the output:
Current Deployment Environment: :localhost
Features:
- new_algorithm is ON. Enabled in [:localhost, :staging]
- new_ui is OFF. Enabled in [:staging]
Completing the Experiment: Retiring :new_algorithm or Rolling it Out to :production
If, after experiencing :new_algorithm is :localhost and :staging, you decided that the world is not ready for its genius, you can simply remove new_algorithm and its implementation from configs and the codebase.
If you are now confident that this new_algorithm for computing 𝝿 will make the world and your product better, and you want to roll it out to production, you have a couple of options:
- Remove the feature flag completely. The new feature is now part of your codebase.
- Add your production environment to the
enabled_in:list, or replace the list with:all:new_algorithm: %{enabled_in: [:localhost, :staging: :production]},ORnew_algorithm: %{enabled_in: :all},.
A/B, Regional Testing
The example above alluded to the existence of :localhost, :staging, and :production deployment environments.
The configuration approach of choosing the environments in which your changes are live remains the same, regardless of how many production or staging environments you have: simply detect current_deployment_environment in which the code is running, and include all environments of interest in the enabled_in list.
For example, to roll :new_algorithm out to your production environment running in Singapore, but not to the US or Japan, you might do something like this:
config/runtime.exs
# e.g. :localhost, :staging, :production_us, :production_sg, :production_jp
# Detect this in runtime.
current_deployment_environment = ...
config :simple_feature_flags, :flags, %{
current_deployment_environment: current_deployment_environment,
features: %{
# enabled in production in Singapore.
new_algorithm: %{enabled_in: [:localhost, :staging, :production_sg]},
}
}