In a traditional software development workflow, whenever there are updates or feature releases to be made, they are typically tied to a single major deployment to production. As a result, the frequency of feature delivery is slower and a lot riskier because there’s a lot more at stake with each deployment if things don't go as planned.
That is to say that releases should not be tied to deployments but rather, decoupled from them. Due to this reason, in a continuous delivery environment, it is considered best practice to decouple feature releases from deployments as it allows for more incremental releases.
Hence, understanding the concept of decoupling releases from deployment and how feature flags can make that possible is a key for any team.
Deployment: When we refer to "deployment" we mean the action of pushing code from a development environment to the production environment or a certain part of our infrastructure. This deployed code could contain one or more updates, features or functionalities.
Release: When we refer to "release" we mean the actual act of enabling or exposing a change, feature, or functionality to our end-users.
The difference between both is that when a feature is deployed, it does not necessarily mean the end-user now has access to it. No! It simply means the feature has been pushed to the end-users environment (i.e. production environment), whereas, releasing the feature is the action of exposing or turning it on, so it is available and accessible to the end-user.
The typical development workflow involves collaborating in teams on any given product or feature where each team member works on a different feature branch. However, when collaborating in parallel it’s often not feasible to wait until every developer has completed their work before making a deployment.
Sometimes certain features may be ready before others are, or may need testing on users in a live environment so as to gain immediate feedback to aid iteration and modification.
Ideally, you want to be able to push these features when they are ready for release or live testing into production and expose some users to them. At its core, the reason for decoupling releases from deployment is to be able to deliver new features to users faster while mitigating some deployment risks and without compromising on software quality.
Decoupling releases from deployment gives you control over when and how a release is made even after deploying to production. Should something go wrong with a release, you only need to "un-release" these changes rather than having to do a full rollback to the previous version or having to hastily build a potentially buggy patch.
Imagine for a second, that you are the owner or manager of a retail store where thousands of customers shop daily. When your supplier or manufacturer supplies you with a new range of products, and you move them from the warehouse to the store (i.e. deployment).
You don't just throw everything on the shelves so that people can buy them (i.e. release). You may choose to put only a few on store shelves to test them out and to see how customers interact with them. That is the same as decoupling your releases from deployment to perform a selective release.
Feature flags (also called feature toggles) play a key role in continuous delivery, specifically in the concept of decoupling feature releases from deployment as they make it possible to deploy code behind conditional flags, and then only toggling them on/off to expose or hide said code from users as the need arises.
Feature flags provide several interesting features that facilitate decoupling and testing in production, such as being able to target a specific subset of users or user groups, or a percentage (portion) of your traffic, as well as providing accompanying kill switches for easy rollbacks.
By feature flagging, you can safely push code to production without immediately exposing it to users, experiment with A/B tests, release by user segmentation, reduce the risk associated with deployment by making incremental updates and be able to turn a resource or feature on/off at will.
Luckily you don’t need to worry about building or managing your own feature flags as there are companies such as ConfigCat that offer feature flags as a service, making it easy to integrate a feature flag management system into your releases.
When you release an update or a feature to production, phased rollout enables you to implement your release in stages via user segmentation. Phase rollout lets you break your releases into stages by targeting only a subset or percentage of users at a time. This lets you gradually ramp up the number of users exposed to your release until the release is made available to all of your users.
You can start by releasing it to the first 1% or 5%, then ramp it up to 10%, 20%, 50%, 75%, and finally 100%. This strategy lets you control the blast radius (limit the scope of potential issues) of a release and makes it possible to test and gain immediate feedback early on from your users. For example, if a release performs poorly or is buggy, it's better if only 5% of users experience this rather than your entire user base.
Furthermore, staged rollouts are also useful for experimenting with new features, such as doing A/B testing. Instead of pushing out releases to all users simultaneously, you can use controlled, measurable feedback to determine what's working in a phased rollout release.
As the name implies, a dark launch is usually not publicized, but rather rolled out stealthily by first releasing to a subset of users before a full release to see how they perform. Usually, users are unaware they are testing out the new feature or functionality; rarely will the new feature be announced or highlighted until it’s ready for full release.
As a result, development teams can get early feedback from users, test bugs, and even stress test infrastructure performance. This allows for faster, iterative releases, and ensures that application performance is not affected, and the release is well received by users.
This release method was popularized by major tech companies such as Facebook and Google to test upcoming features by pushing them out to a subset of users before an all-out release.
Decoupling releases from deployments using feature flags has several key benefits:
- Get Code to Production faster - Decoupling your feature releases from your deployment makes it possible to release more frequently.
- Risk Mitigation - Easily control the blast radius of your releases.
- User Targeting - Through user segmentation, the visibility of features can be targeted to certain users.
- A/B Testing - Easily run A/B tests of features to see which performs better.
- Percentage Rollouts - Release features incrementally to your users to gain feedback early on that can be used to improve it further.
- Trunk Release - You can release parts of the code and push them into production even if some features are not yet ready for deployment by keeping them toggled off.
- Kill Switch - Quickly roll back a feature when it is performing poorly or is buggy.
- Avoid Branching and Merging - Rather than having to keep maintaining separate feature branches for a new feature, you can avoid potential merge conflicts using feature flags to conditionally enable features when they're ready.
The idea behind decoupling releases from deployment with feature flags is to maintain a fast, continuous integration feedback loop. This makes it possible to rapidly deliver updates to production and test new features without impacting your infrastructure or disrupting your user experience.
Decoupling your releases from your deployments gives you greater control over your feature releases. As a result, you can push code anywhere and at any time without exposing your users to deployment risks.