Skip to main content

Haskell Feature Flag Demo (Part 1)

Brandon Chinn posted an interesting challenge to Haskell Discourse yesterday. He is working on a Haskell project that requires the use of “feature flags,” configuration that allows you to enable or disable specific features without having to rebuild or redeploy the software. I made a quick demo of my ideas and am writing about it in this blog series. This first entry in the series describes the problem.

If used at all, feature flags should be used with care. A feature flag should be temporary. If the purpose of a feature flag is to make it easy to rollback a change, as seems to be the case in Brandon’s project, it should be removed from the project once the correctness of the change has been verified. If a feature flag is used for A/B testing, it should be removed from the project once testing is complete. Supporting many feature flags simultaneously should be avoided, as it can greatly increase the cost of development and maintenance.

Here is a summary of Brandon’s implementation requirements:

  • Feature flags are configured in a database, and the software loads the current configuration at start. What happens if the software is unable to successfully load the configuration is out of scope of the challenge.
  • The software loads the configuration exactly once, and it is immutable while the software runs. Changes to the configuration only affect later runs of the software.
  • The Haskell API should not require significant refactoring of an existing codebase. The configuration should be accessible from any IO action, without having to explicitly pass it nor refactor to use ReaderT.
  • Tests must be able to run against various configurations.

The title of Brandon’s post is “Challenge: FeatureFlag pure functions,” which explicitly mentions pure functions. I created a demo to show a way to tag feature flag configuration, to avoid “boolean blindness.” This makes it difficult to pass the wrong configuration to a pure function.

I am writing a blog series just so that each entry is not too long.

  • Part 2 presents an implementation using simple types. This version suffers from “boolean blindness:” it is possible/easy to pass the wrong feature flag configuration as an argument.
  • Part 3 presents an implementation that addresses this problem using tagged feature flag configuration.
  • Part 4 presents the tests for both of these versions.

The full source is available on GitHub.