At WillowTree® we try to fully leverage the power of the cloud whenever possible. During one of our recent projects, we saw the opportunity to migrate the existing database from a virtual machine based deployment to a cloud-managed solution. This change ended up reducing both financial and operational cost for our client. We chose to migrate to Azure Cosmos DB–a migration we recently explored on our blog. For this article, I wanted dig deeper into our migration, and offer some insight on two key assets that made a difference for our team–feature flags and the facade pattern.
Feature flags are a current best practice to decouple deployment from exposure. A single release artifact can have features conditionally enabled without requiring a new deployment. These flags can be used to implement a variety of features, such as user-based opt-in, A/B testing, incremental rollback, and the graceful sunsetting of features.
Feature flags are integral to implementing other modern best practices such as trunk based development, branch by abstraction, and continuous delivery. For example, frontends can hide screens, buttons, or options until the API is ready, preventing the need for long living branches. APIs can selectively enable endpoints or request/response fields. With feature flags, you can continuously deliver your applications and delay exposure until ready.
The combination of trunk based development and feature flags provide several benefits over Gitflow and other branching strategies. With Gitflow, a feature is not merged in until it is ready for release. In addition, you are only able to rollback at the release level, not the feature level. Feature flags allow us to concurrently develop, continuously integrate, and incrementally deliver.
The simplest implementation of a feature flag is an “if/else” statement and a boolean variable sourced from the environment.
With no dependencies on external libraries and no reliance on specific language features, this is an ideal implementation for easing feature flags into your development process.
The flag doesn’t have to come from the environment, however. If you are implementing a user opt-in feature, the flag can be a part of the user record.
The developer doesn’t have to be the one doing the toggling. The product owner, manager, or customer could be the one enabling the flags. In fact, the flag could even be toggled by some automated external factor, like a countdown clock for a product launch–for example. Be sure to take these use cases into account when designing those particular flags and the toggle mechanism.
The facade pattern is one of the original “Gang of Four” design patterns. Its purpose is to hide complex or ugly logic behind a pleasant interface, much like an architectural facade.
We chose to utilize the facade pattern to hide the usage of feature toggles from consumers. In our software architecture, we utilized the repository pattern to create a clean separation of data storage/retrieval logic and the rest of our application. We created facade repositories that wrapped a primary and a secondary repository. All toggle logic was encapsulated in these facades, which meant that no consumer code had to change.
We implemented new repositories and facades over the course of several sprints. We were able to concurrently work on several repositories at once without interfering with each other because we used the facade pattern. Setting the primary database to point to the old database, allowed us to continuously deliver to production without interrupting the user experience.
Once we were ready to test the new database, we simply flipped the toggle for a particular repository. On occasion, we needed to rollback due to performance issues. Because we were always writing to both databases, this rollback had very low risk.
When we were satisfied with the performance for a particular repository, we removed the old repository and facade code, and simply injected the new repository. No consumer code ever needed to change. We continued removing old code–repository by repository– until we were finished with the migration.
The union of feature flags and the facade pattern turned what could have been a Herculean task into very manageable work. Our methodical approach allowed us to juggle creating new features, production operations, and the migration itself with relative ease.