Pete Hodgson on Feature Toggles

Pete Hodgson, a fellow ThoughtWorker, is writing about Feature Toggles on Martin Fowler’s site.

We use feature toggles in the OpenMRS Reference Application to allow incomplete features to be written in the master branch of code, while still allowing us to release that code on a moment’s notice, to follow good CD practices.

If you’re interested in reading a comprehensive treatment of the Feature Toggle pattern, this is good:

2 Likes

Thank you for sharing this @darius!

Nice article. I totally get the benefit of toggles and think we should be using this pattern († caveat below).

The piece that I’m most interested in was missing from the article: what about the database? In other words, what are the best practices for feature toggles that involve database schema changes, especially if data needs to be migrated or transformed for the feature? For example, if we are building a feature to move from our boolean estimated birthdates (exact vs. estimated) to allowing various levels of estimation (approximate year, exact year, exact year+month, exact year+week, exact date), how would we feature toggle the database changes? Do you make the changes in the database and then limit the feature toggle to how they are used? Or do you copy the existing data into the new format (keeping both formats persisted for the time being) and feature toggle which is used? If so, how do you keep them sync’d? Another, perhaps simpler, example would be adding a column to the obs table. Are there best practices or common pitfalls when creating feature toggles that involve database schema changes? Are there any good guidelines for how to plan for such feature toggles?

@burke this is an interesting topic.

There is a book about called Refactoring Databases: Evolutionary Database Design. In a short summary, in a continuous delivery world your changes on the DB should be backwards compatible. What does that mean varies case by case, but usually means doing structural changes in few steps rather than doing in a single migration. I haven’t read the whole book yet, but it is awesome book to read if you want to learn more about that.

If I understood it correctly, these toggles are temporary. Once the new feature is well tested the old code can be removed, along with the toggle.

In theory they are temporary, but if you’ve got a lot of development going on at slow pace, they can hang around longer than one would like… :slightly_smiling:

Mark

True. And sometimes they are permanent, for instance with multiple customers having different requirements.

Yep, you are right–you add a toggle for a new function that you assume will be used by everyone, and then one customer doesn’t want it, or at least isn’t ready for it, and it hangs around longer than expected… this has happened across our multiple implementations.

This isn’t to say I’m arguing against feature toggles–they have been very helpful for us.

I should say more about feature toggles for OpenMRS.

Feature Toggles are a very powerful design pattern to enabe Trunk Based Development and Continuous Delivery, but they must be used with discretion and they require discipline on the part of a developer.

Since we only sort of do continuous delivery, and we have multiple teams and individuals working on the same codebase with very loose coordination, things get tricky.

  • There is already a framework implemented for them in the App Framework, further supported by App UI and UI Commons. It is documented on this wiki page.
  • Feature Toggles are a temporary tool for developer convenience at the user-facing level of the application. They are not appropriate for “multiple customers having different requirements”: that kind of configurability is its own proper feature, and they wouldn’t be appropriate for making and then reverting a database change.
  • They should really only be used when:
  • a team (or individual) is putting sustained effort into building the feature, and won’t disappear without having finished it and removed the toggle
  • the broader codebase will need to be released while the feature is partially-committed
  • the feature needs to be tested in a QA environment without affecting production
  • the team will remove the toggle when the feature is complete (and isn’t depending on an implementation’s timeline)

The Ebola project couldn’t have worked without Feature Toggles. We needed to be able to deploy frequently to production, in whatever time window the ETC would allow us. But we also couldn’t afford to slow down development and testing by putting things in branches.

On the Mirebalais project it was a more qualified success. They were very helpful overall, but in some cases we got stuck with some completed features that stayed toggled off for months because the implementation wasn’t ready for them. (Not a big problem for the PIH team, but for OpenMRS this meant that completed features ended up sitting in the Core Apps module for a very long time without being turned on. We would have been better off building an actual feature for real configurability.)

I also used a feature toggle to a feature I was building as part of a tutorial, and left halfway done. So that toggle is still in the code. So that’s an example of what not to do. (See RA-350)

To sum up, they can be really helpful, but they should only be used in the context of a concerted, reliable effort. You need to finish the work, and remove the toggle.

1 Like

Thanks for the reference, @marioareias. I’m curious whether these approaches depend on stored procedures or other low-level database features. Certainly database refactoring (supporting migration & feature toggles that include database changes) would require additional thought & planning beyond a liquibase entry when introducing database changes, but my gut instinct is that there are probably a handful of patterns that could be used to cover a majority of cases (i.e., we could repeat these patterns instead of having to invent a solution from scratch each time).

In my experience, “temporary” in software development can be anywhere from 1 week to 30 years. :wink: