Rollback a Flipper Feature Flag Release
by Josh Branchaud
Flipper ↗ is a lightweight gem that provides many basic features one could need to introduce feature flagging into their Rails app. I've found it to be effective on a recent project and would use it with other projects going forward. One medium-sized gotcha that I think is worth noting is that un-releasing a feature doesn't restore pre-release actors.
Let me explain.
When I first start developing a feature behind a Flipper feature flag, I gate
everything related to that feature. Then as it hits staging and production, I
will enable that feature for certain people on the team, including myself. That
is done by adding actors to that feature (e.g. in the form User;<USER-ID>).
Then as we want to roll out the feature to some specific pilot customers, we
will add their users as actors with feature access.
This list of enabled actors grows a little until we are ready to fully enable the feature. When we flip that switch, all the internal records of which users were enabled as actors on that feature are wiped out. On the one hand that makes perfect sense as a design choice because the flag being fully enabled short-circuits a need to check individual actors.
There is a specific important scenario where this design decision can really bite. Let's say some edge case or business decision arises after fully releasing a feature that necessitates turning that feature back off. I'd like to "rollback" to the state where this feature was enabled for a handful of specific actors. Instead that data is lost and it is now disabled for everyone.
One way to work around this is to capture a snapshot of all the actors that were enabled for a feature before enabling it.
actors = Flipper[:some_feature].actors_value.to_a
puts JSON.pretty_generate(actors)
I can stash that list somewhere and loop over it in the production Rails console to recreate those actors after disabling the feature.
Here is an example of a script I could use (that is, paste into rails console)
if I need to rollback a fully enabled feature:
# rollback_feature.rb
#
# Paste snapshot JSON here:
ACTOR_IDS_JSON = <<~JSON
[
"User;123",
"Organization;3d9b16b0-1183-41ac-bdc6-9deeda7754d2",
...
]
JSON
FEATURE_KEY = :some_feature
# Turn off the boolean "fully enabled" gate
Flipper.disable(FEATURE_KEY)
# Rehydrate per-actor gates
JSON.parse(ACTOR_IDS_JSON).each do |flipper_id|
Flipper.enable_actor(FEATURE_KEY, Flipper::Actor.new(flipper_id))
end
puts "state: #{Flipper[FEATURE_KEY].state}"
puts "actors: #{Flipper[FEATURE_KEY].actors_value.to_a.sort.inspect}"
If you want a more dedicated solution to this, I believe that Flipper Cloud ↗ offers a feature to rollback to the previous state of a flag.