You’re on a team that wants to ship a Super Cool New Feature™.
The feature will cause changes all over your web app. Instead of releasing the work in pieces, the marketing team wants to have a big reveal to create a buzz. How do you manage this challenge?
One option is to keep all the work in a separate code branch. When everything is done, merge the code back into your main branch, ship it, and reveal it to the world. Whoa, hold on, that sounds risky.
What could possibly go wrong? Well, how about:
That sounds… terrible.
How can we continuously deliver the feature without killing the marketing buzz? We can use feature flags.
Feature flags are a tool that give development teams the ability to expose a feature in a controlled manner.
You might come across feature flags as feature toggles or feature flippers. Even though the names are different, the intent is the same. With feature flags, a team controls which features are active and which people see those active features.
A feature flag functions as a configurable point in a system that a team can enable or disable. In code, a feature flag looks a little like:
if feature_flag_is_active: return super_cool_new_feature() else: return old_behavior()
feature_flag_is_active true or not can depend
on who the user is.
This extra level
to gate the release.
We could enable our Super Cool New Feature for the marketing team (or QA) in advance. This gives them time to review, provide feedback, and let’s us address bugs.
I can tell you from personal experience that mastery over the feature timeline is a huge boon for Storybird. The team at Storybird can polish features before sharing them with hundreds of thousands of teachers and students.
Now that you’re equipped
with the knowledge
of what feature flags are,
let’s explore one library
that implements them.
Go get the syrup
because we’re going to be talking about waffles,
waffle: verb - EQUIVOCATE, VACILLATE
Django Waffle is a feature flag library that can enable or disable code, as described previously, and is quick to add to any Django project.
Waffle includes a few types of feature control. For our purposes, I’m going to focus on flags as they are the most interesting and powerful type.
waffle.flag_is_active is the critical method
for the Waffle flags API.
Suppose part of our Super Cool New Feature is a new template design for our product page. If the original product view looked like:
class ProductView(View): def get(self, request, *args, **kwargs): # Do work to build template context... return render(request, 'old_design.html', context)
Then our new code that adds a Waffle flag would look like:
class ProductView(View): def get(self, request, *args, **kwargs): # Do work to build template context... if waffle.flag_is_active(request, 'super_cool_new_feature'): return render(request, 'new_design.html', context) else: return render(request, 'old_design.html', context)
Let’s break down how this works.
Waffle stores flag settings in a database table. A team controls the available flags via the Django admin. From the admin site, a developer can set a flag’s name, enabled/disabled status, and some filters for more specific control like superuser, staff, or specific group access.
When the view executes,
against the settings decribed
super_cool_new_feature database row.
If the user meets the criteria,
the function evaluates to
and your new code will run.
For the Super Cool New Feature, Waffle can be called in every place that needs to be changed using the same feature flag name. This introduces a way to turn the feature on (or off!) with a quick edit in the Django admin.
Maybe you’ve come this far and a question has percolated up through your mind.
Isn’t this more complicated?
Yes, it is. Like every engineering choice, feature flags have trade-offs.
By adding a feature flag directly to the code, we create clean up work when the feature flag is no longer needed. This clean up work takes time, but it is better than the alternative. A long lived feature branch almost always causes trouble.
Feature flags divorce the shipping of features from the revelation of features.
This flexibility is great for teams that need to move fast. And there are amazing side benefits like creating a work culture that delivers code constantly. Constant delivery builds trust between an engineering team and other teams because of a tight feedback loop. If you’re looking for a way to move your team faster and improve your workplace, give feature flags a shot!
If you want to chat about this with me, I'm @mblayman on Twitter.
In this series of posts, I'm going to examine common design patterns in Python that make Python code feel "Pythonic." The sixth and final post explores the Python Package Index, and the benefit of using software libraries that are written by others to make your code more expressive.
Matt is the lead software engineer at Storybird.
Always eager to talk about Python and other technology topics, Matt organizes Python Frederick in Frederick, Maryland (NW of Washington D.C.) and seeks to grow software skills for people in his community.