How to audit Feature Flags with FunWithFlags and ExAudit

Auditing Feature Flags - AI generated image

AI generated image - obviously :P

Feature Flags are a powerful tool to manage features in your application. They allow you to control the visibility of features, and can be used to manage feature rollouts, A/B testing, and more. At Up Learn, we mainly use it to manage feature rollouts and to show features according to user groups (A Level students, GCSE students, internal Up Learn users, etc). To implement feature flags, we use the FunWithFlags library. It is an Elixir library that provides a simple API to manage feature flags, allowing for toggling features globally, or for specific user groups or even for specific resources (e.g. feature enabled just for a specific course).

With the growth of our application and our team, we saw the need to audit every change on our feature flags to know when and who changed it. For auditing, we already use ExAudit, an Ecto auditing library that transparently tracks changes and can even revert them. ExAudit wraps around functions in your Repo module to track changes made to the tracked schemas. It stores the changes in a separate table, and you can query the changes made to a specific record.

When we implemented auditing for our feature flags, there wasn’t much information on the web on how to do it. As there are some caveats when integrating FunWithFlags and ExAudit, I decided to write this post to help others who might be looking to do the same. It assumes you already have FunWithFlags and ExAudit set up in your application.

First things first, let’s add the feature flags schema to ExAudit config. On your config.exs file, add the following:

config :ex_audit,
  ecto_repos: [MyApp.Repo],
  version_schema: MyApp.Version,
  schemas: [
    FunWithFlags.Store.Persistent.Ecto.Record
  ]

Here is already a caveat! Even though we have a schema for our feature flags called UpLearn.Features.FeatureFlag, we need to add FunWithFlags.Store.Persistent.Ecto.Record to the ExAudit config. This is because FunWithFlags uses an underlying schema to store the feature flags, and we need to track changes on that schema. Even though this is a schema internal to FunWithFlags and not part of our application, this was the way we got ExAudit to work with FunWithFlags.

After that, every change made to the feature flags will be tracked by ExAudit. FunWithFlags uses a single table to store all of the flags, independently if they are global or for specific user groups. For some reason, the ExAudit changelogs tracked are all recorded as created, even when we are updating the feature flag. You can then query your MyApp.Version schema to see all the changes made to the feature flags.

Other than that, the integration is quite smooth and straightforward. We now have a clear view of who changed the feature flags and when. This is a great addition to our application, and I hope this post helps you to integrate FunWithFlags and ExAudit in your application as well!