Issue 07

How to build the simplest feature flag system in Elixir & Phoenix apps

A guide for Elixir developers (and why you might want to)

Aug 3, 2022 · 3 minute read

What is a feature flag?

Feature flags are a common technique used in software engineering to easily turn select functionality on or off during runtime.

Ideally these systems don't require any deployment but for the purpose of this tutorial I'm going to be sharing the mechanism I built in about 3 minutes for madepublic.io.

If you need a full on solution I recommend checking out the excellent Fun With Flags library but for my purposes I needed something that I didn't need to configure, that would allow me to hide new functionality from production (that wasn't ready yet) and carry on developing them in dev and test runtimes.

This mechanism requires deployment but since I'm deploying with fly.io, it takes all of 90 seconds to push up my changes which is great for me - I want to spend my time building useful features over tooling.

On with the building!

We want something flexible so lets make sure this mechanism is flexible enough to handle other features I want to do this with in the future.

So I want to essentially not render certain templates or code if a feature is turned off - let's do that.

First, let's define a module that can read from our Application environment variables:

# lib/features.ex
defmodule Madepublic.Features do
  def feature_available?(feature_key) do
    Application.get_env(:madepublic, :features)[feature_key]
  end
end

For this to work we need to add new variables to our config files, let's use a keyword list so we can define more in the future.

We also want to make sure that we have a default set - I want every environment other than production to have this feature turned on - for that we can use the config.exs file to specify a default, then change it on a more granular level for production by overriding it in prod.exs.

# config/config.exs
config :madepublic, :features,
  auth: true

# config/runtime.exs
if config_env() == :prod do
	config :madepublic, :features,
		auth: false
end

Sweet - we have the feature but we want it to be available to every template we might have.

Let's hope into our web.ex file and include our new module in our view_helpers.

# lib/madepublic_web.ex
defp view_helpers do
  quote do
    # all the original imports and aliases
    import Madepublic.Features # <- New addition
  end
end

Now let's give it a whirl:

# In any of my templates or .heex files
<%= if feature_available?(:auth) do %>
    <%= render "_user_menu.html", assigns %>
<% end %>

Localhost

Locally

Production

Production

It works!

We have a repeatable, simple feature flag system that we can use to slowly unveil features to our users.

I hope you found this tutorial useful, subscribe to my Substack below for similar content and follow me on Twitter for more Elixir (and general programming) tips.

If you're building a side project I'd also encourage you to take a look at madepublic.io!

Enjoyed this content?

Want to learn and master LiveView?

Check out the book I'm writing

The Phoenix LiveView Cookbook
fin

Sign up to my substack to be emailed about new posts