DevOps enables us to deliver at speed, learn from production feedback, make better educated decisions, and increase customer satisfaction, acquisition and retention. We need to fail fast on features that result in indifference or negative user experience and focus on features that make a positive difference. Progressive exposure is a DevOps practice, based on feature flags and ring-based deployment that allows us to expose features to selected users in production, to observe and validate, before exposing to all users.
You're probably asking yourself whether to use ring-based deployments, feature flags, or both to support progressive exposure in your environment. Let's start by exploring these strategies.
Ring-based deployment was first discussed in Jez Humble's book Continuous Delivery, as Canary-deployments. Rings limit impact on end-users, while gradually deploying and confirming change in production. With rings we evaluate the impact, "blast radius", through observation, testing, diagnosis of telemetry, and most importantly, user feedback. Rings make it possible to progressively deploy binary bits and have multiple production releases running in parallel. You can gather feedback without being at risk of affecting all users, decommission old releases, and distribute new releases when you are confident that everything is working properly.
The following diagram show an implementation of the ring-based deployment process:
When your developers complete a pull request with proposed changes to the master branch, (1) a continuous integration build performs the build, unit testing, and triggers an automatic release to the Canary environment in production. When you're confident that the release is ready for user acceptance and exploratory testing in production (2) you approve the release to the Early Adopter ring. Similarly, when you're confident that the release is ready for prime time, (3) you approve the release to the Users ring. The names and number of rings depends on your preferences, but it's important that all rings are using the same production environment.
Feature Flags were first popularized by Martin Fowler. Flags decouple release deployment and feature exposure, give run-time control down to the individual user, and enable hypothesis-driven development. Using and tying feature flags back to telemetry, allows you to decide if a feature helped to increase user satisfaction, acquisition, and retention. You can also use feature flags to do an emergency roll-back, hide a feature in a region where it shouldn't be available, or enable telemetry as needed.
A typical feature flag implementation is based on (1) a management service that defines the flag, (2) a run-time query to figure out the value of the flag, and (3) an if-else programming construct, as shown:
Both the feature flags and ring-based deployment model strategies are invaluable, whether you're working with an open source extension community, or moving 65,000 engineers to DevOps.
The quote “You do not respond to a mosquito bite with a hammer.”, by Patrick L.O. Lumumba, comes to mind.
We use both rings and feature flags to progressively expose a new release in production, whether it's a hot fix or feature release for our commercial product, affecting 65,000 engineers and eventually hundreds of thousands of users as the blast or impact radius of the release increases. Feature flags allow us to progressively reveal new features of each release, perform A|B testing, and experiment in production. Because we're working with cloud services and extensions, we have a continuous feedback loop with our users and the ability to fine tune each release by toggling feature flags.
For our open source community extensions, we're primarily using ring-based deployment to progressively expose a new release to canary, early adopters, and users as outlined in the table below. We're gradually implementing feature flags in selected extensions to experiment and gather experience in fine tuning features and managing the associated technical debt.
The quasi-continuous delivery mode is another example of using both strategies to deploy new features to 1% of the users in the first ring, then 20%, 50%, and 100%, continuing with the same pattern to the second ring, and so on.
You can use either ring-based deployment or feature flags to implement the progressive exposure DevOps practice - they are symbiotic. It all boils down to how cautious you want to be when rolling out releases and exposing features. I recommend that you experiment with both. Start by using deployment rings to progressively expose a new release, then use feature flags to fine tune each release in production.
I think of a when using the ring-based deployment model to deploy a release and a when using feature flags to fine tune the release.
Happy ringing and flagging!
Table comparing rings with flags within the context of our open source extensions:
DEPLOYMENT RING | FEATURE FLAG | |
---|---|---|
Progressive exposure | Yes | Yes |
A/B Testing | All users within ring | All or selected users |
Cost | Production environment maintenance | Feature Flag database and code maintenance |
Primary use | Manage impact "blast radius" | Show or hide features in a release |
Blast radius - Canaries | 0-9 canary users | 0, all, or specific canary users |
Blast radius - Early Adopters | 10-100 early adopter users | 0, all, or specific early adopter users |
Blast radius - Users | 10000+ of users | 0, all, or specific users |
For more details refer to Software Development with Feature Toggles, Phase the roll-out of your application through rings, and Our Feature Flag Investigations.