Skip to content

Feature Flags

Feature flags is a way to have features under development live on production and visible only to admins/beta-users.

The idea of Feature Flags came from Flickr. They manage their development on a single branch using feature flags. See Flickr's blog post on flipping out with feature flags

Using Feature Flags

Feature flags are used in templates and in controller classes. To make some part of the template visible only if a feature-flag is enabled:

py
$if "lists" in ctx.features:
    <h3>Lists</h3>
    $for list in page.get_lists():
        ...

To enable a url only if a feature flag is enabled:

py
class home(delegate.page):
    path = "/"

    def is_enabled(self):
        return "home-v2" in web.ctx.features

    def GET(self):
        return render_template("home")

Setting Feature Flags

In Open Library, the feature flags are specified in the openlibrary.yml file as follows:

yml
features:
  merge-authors: enabled
  lists: admin
  lending_v2:
    filter: usergroup
    usergroup: beta-users

The value of a feature flag is called a filter. A filter can be specified either as its name or as a dict containing its name and parameters. For example, the following 2 example mean the same.

yml
features:
    lists: admin

features:
    lists:
        filter: admin

Available filters are:

  • enabled

    Enabled for all users.

  • disabled

    Disabled for all users.

  • loggedin

    Enabled only for logged-in users.

  • admin

    Enabled for admin users.

  • usergroup

    Enabled for the users part of the specified usergroup.

yml
lending_v2:
  filter: usergroup
  usergroup: beta-users
  • queryparam

    Enabled only if the url has a specified query parameter.

yml
debug:
  filter: queryparam
  name: debug
  value: true

How queryparam works

Notes for core developers: In infogami's feature module, a few types of filters are defined. One of them is filter_queryparam which checks that the feature's value equals a query param provided with the request.

When the request is processed, the infogami loadhook, runs find_enabled_features() which invoked the necessary filter(s) via call_filter that make sure when features.is_enabled(feature_name) is called, that the correct answer exists for feature_name.