Introduction
Feature Flag is a well-known technique to modify system behaviour without changing code.
As of today, besides Martin Fowler's blog, we have a lot of posts and youtube videos to know how Feature Flag looks like.
However, if you'd like to introduce it into the system, probably you will face some issues to consider and discuss to develop your own Feature Flag.
In this article, I am going to address what came up as the issues in front of my team, and show how I lead the first version of Feature Flag of the company with the Rails code example.
Feature Flag of a team or a company?
My company has several backend teams and frontend teams. So the first question is, each team can have its Feature Flag system or not?
The decision was NO at that time. Why it is better to have a unified, centralized Feature Flag system as a company? That is because it becomes out of our control soon if we have multiple flagging system.
For instance, let's assume we develop a new feature A by team 1 and team 2. If we have an independent Feature Flag system, we should make sure both A's flags are in a correct status in both of team 1 and team 2 Feature Flag system. But, what if we have feature B simultaneously? What if team 3 is also involved? Easily variables would increase right after starting the operation.
However, this decision has also a drawback. Once a certain team starts creating Feature Flag Service, other teams should wait until the team provides API to use Feature Flag.
What toggles should be included in the first version?
When you hear the word, Feature Flag, what comes up in your mind? It enables us to do the A/B test. It works like a circuit breaker. It provides premier features to limited users, etc.
Yes, if we say Feature Flag, it has a variety of features to be implemented. Especially if people have experienced to use sophisticated Feature Flag system like LaunchDarkly, the ideal Feature Flag would have rich functions.
To take a step forward, let's think the first implementation as simple as possible.
As mentioned in this article, it is better to focus on "Release Toggle" to allow deploying on-going code into production. Release Toggle enables us to deploy in-progress code into production. It reduces long held feature branches in your codebase.
How Release Toggle looks like
Let's see a simple implementation of Feature Flag which implements Release Toggle.
class FeatureFlag
def self.enabled?(feature_name)
case feature_name
when 'awesome-feature'
true
else
true
end
end
end
The simplest example would be like this, but it seems not practical to operate the real-world application. So, what should be considered to introduce it into our application?
1. Default return value
Else block of the above example is the default value that would be returned if the specified feature name doesn't exist. In this case, should we return true or false? Or, better to raise the exception?
The purpose of Feature Flag, especially Release toggle, is to make Deploy and Release independent. From that aspect, the codebase won't need to know what kinds of feature flags are defined. Meaning we should not raise the exception because the non-existence of a specified feature flag is not the exception. Further, it would be better to return false than true because in most cases, we would use a feature flag when we want to launch a new feature. If so, when the specified feature flag doesn't exist, nothing happens would be a preferable behaviour. Given that, returning false is safer to operate the real world application.
2. The number of flags
Feature Flag is magic. Once it is introduced into the product, everyone uses it to make their work easy. Eventually, there would be tens or hundreds of flags and our Feature Flag would be out of control. To prevent the worst-case scenario, having a limitation for the number of flags is a good practice. 5-10 would be a good start!
3. How to manage the flags
As you see in the example, hard-coding flags into the ruby file look not practical. What would be good to set them up then? RDB seems reasonable, they are reliable, add/delete operation is easy, and it's needed if we make UI. But this is the very first version of Feature Flag. Maybe we would expand what Feature Flag can do in near future. Given that, we want to avoid over-technology. From that aspect, YAML would be a good candidate to manage flags. And if that YAML file loaded during booting up the app, seems great. We can make it easy by using Rails legacy.
How the practical FeatureFlag looks like
Following the above aspects, let's refactor the code.
feature_flag.rb
class FeatureFlag
def self.enabled?(feature_name)
if @features.key?(feature_name.to_s)
@features[feature_name.to_s]
else
false
end
end
def self.load
@setting = YAML.safe_load(File.read(config.setting_path))
@features = @setting['features']
raise "The number of flags is limited to #{config.feature_limit}" if @features.count > config.feature_limit
end
def self.config
@config ||= Config.new
end
def self.configure
yield config
end
class Config
include ActiveSupport::Configurable
config_accessor :setting_path do
''
end
config_accessor :feature_limit do
0
end
end
end
config/initializers/feature_flag.rb
FeatureFlag.configure do |config|
config.setting_path = Rails.root.join('config', 'feature_flag.yml')
config.feature_limit = 5
end
FeatureFlag.load
config/feature_flag.yml
features:
awesome-feature: true
Looks way practical, doesn't it?
What's next?
You would have two dimensions to expand this Feature Flag. 1. Adding new Toggles and 2. providing API for other teams. We now have the exact example as the code. It would make clear what we should do next, what we can, how long it would take. That enables to involve non-developers into the discussion!
Conclusion
Feature Flag is a very useful, powerful feature and it's discussed for a long time. However, there are few examples if you want to refer to implement your own Feature Flag.
Hope this article helps to solve your concerns, and can earn the huge benefits of FeatureFlag!
Top comments (2)
I like this idea, but is there an example of how to use the Feature Flag?
Would it be something like:
So in this case to flip the feature flag would require restarting the server?
Yes it should be like that.
This implementation requires rebooting the app instance, but this is beneficial if you have several web servers to distribute the yaml file