Feature flags in a Single Page Application: a cookbook


About feature flags

Feature flags are awesome: they allow you to enable/disable one or many features in your application at runtime. Why is it important? Because it allows to release many flavours of an application with a single codebase.

Maybe it doesn't sound much, but here's the gist: Your end-users and your QA team will deal with the same codebase, but your QA can test this brand new feature you're working on while end-users do not even notice.

Among the many benefits are:

  • prevents us from doing branch-based deploys
  • allows to test the new features against the most recent codebase
  • allows to ship a new feature bit by bit
  • we only deal with the master branch: no more hotfix on many branches, no more backports, etc.
  • we deploy the same codebase to every environment: no more staging, QA, etc. Everything is handled by feature flags. That's pure bliss, if you ask me.

We've learnt a lot while refining our feature flags strategy, and this post will share the 3 major feature flags strategies we use daily while developing our frontend applications.

The many feature flags

1. The explicit map

The simplest way to define a set of feature flags is to set, somewhere in the configuration of the app, a map of all the available feature flags with their default value:

const features = {
  withLoginScreenWithSocial: false,
  withServiceWorker: false
}

How your app takes into account this map is left to your implementation, but do not forget that as presented here, they are static, which means they can not be changed at runtime.

Allowing to update the feature flag map

It is crucial to offer some way to update this map. In our case, we do as follow:

  • The map is frozen in production environment: it can not be altered by the end users, the set of enabled features is under control.
  • The application has a config page (except in production) that allows to toggle every feature declared in the map. This page itself is enabled on every environment except in production and allows for the (internal) users to try the new features before they are released.

Enabling is manual

The upside of this type of feature flag is that you keep all the control over the status of the feature flag.

The corollary downside is that once it has been approved, you have to manually change the default value to enable it by default, the lifecycle management of this kind of feature flag is more tedious (yet more controlled, let's not forget that) than with the 2 other strategies below.

2. Data-driven feature

For the design pattern lovers, this one could be named "Inversion Of Control" for features.

The idea is simple: Depending on your expectations on the response of an API call, enable or disable a feature.

Here's a simple example: Let's assume that the description of the current user is accessible by performing a GET /accounts/me request. Let's assume that a new feature involves the date of birth of the current user, but alas, it is not available currently.

Here's your feature flag, in a nutshell: If the response payload contains a birth_date property, activate the feature flag withBirthDate. In other (javascript-y) words:

if (payload.hasOwnProperty("birth_date")) {
  features.withBirthDate = true;
}

The main advantage of this type of feature flag is that as you don't get to decide when to enable/disable the feature flag, the feature is automatically in sync with the API (or whatever tier sends the data). Feature flags are rarely frontend-only, so with this one type, not having to sync both ends of the network really helps.

3. Environment-driven feature flag

This last type we try to avoid but it comes in handy from time to time. Here's the gist: We know on which environment we are running based on the current domain; myAppName.local is a development environment, for instance.

So, there are some features that we only enable in some environment. We tend not to do too much because we want to force ourselves into thinking that, from our perspective, an environment is not a solid metric to know what to enable or disable.

It's good to know we can rely on it, but we prefer to be either completely explicit (with a feature map) or data-driven.

Conclusion

There's a lot to be added to cover extended uses of feature flags, such as A/B testing, cohorts, fine-grained activation, lifecycle of a feature flag, etc. but you now have a solid overview of what you can achieve by solely working on your frontend codebase.

Feature flags are of immense help in releasing better software and they are the kind of tools we really like: simple to understand and simple to use.

There is room for more details and more posts will come, but if you can't wait and you want to build frontend applications in a stress-less, fast-paced environment, we're hiring!

More articles

SRE Organization, the Zumba at Guernsey


Context

PeopleDoc is a fast growing company. We now have an innovation lab, and a good amount of feature teams. The number of services running in production is growing, and the dependencies between each service/project at the same time.

The mission of the SRE team is to make sure …

Using Github CODEOWNERS file


Introduction

GitHub CODEOWNERS file is a simple way to automate away some of the pain associated with the review system on github, by automatically assigning reviewers to a pull request based on which files were modified.

How to use

It's really simple ! Just drop a file named CODEOWNERS either at …

How to detect (western) language with Python


Various options for (western) language detection

In order to optimise an NLP preprocessing pipeline, or to be able to tag a batch of documents and to present a user only with results in their preferred language, it might be useful to automatically determine the language of a text sample.

This article presents various ways of doing so in Python, from custom solutions to external libraries. Each solution is evaluated according to three dimensions, accuracy in language detection, execution time and ease of use.

TimescaleDB


This article is about TimescaleDB, a postgreSQL extension, specialized in storing Time Series data. The purpose is being able to easily manage data coming almost sorted on a time dimension. Log or audit events for instance.

Why TimescaleDB ?

PostgreSQL 10 introduces a real partitioning scheme. Before that, users had to …

ANSIBLE_STDOUT_CALLBACK=debug


Un nouveau plugin de type stdout callback fait son apparition dans la release d'Ansible 2.2. Ce plugin est fortement inspiré du snippet qui a tourné quelques années dans la communauté Ansible sous le nom de human_log.py. On peut l'activer avec ANSIBLE_STDOUT_CALLBACK=debug et en appelant ansible-playbook avec -v …

1 / 7