Python Feature Flags: A step-by-step guide to implementing feature flags in a Flask application

By
Matthew Elwell
on
December 2, 2022

Python Feature Flag Introduction

In this article we’re going to learn how to implement feature flags in a basic Flask application, however, this guide could equally be used for any other python web framework like Django or Fast API.

Before we get started with the implementation of the Python feature flag, let’s talk a little bit about the benefits of feature flagging and Flagsmith.

Why Use Feature Flags?

Feature flags allow you to control your application remotely to release new features with confidence. At a very basic use case, you can use them to show/hide new features (which is the use case we will mostly consider). However, they can become very powerful, allowing you to slowly roll features out to a percentage of your users or to show certain features only to a subset of users. Feature flags can also be used to store remote configuration data for your application such as JSON or XML data.

Python Flagsmith

Implementation of Python Feature Toggles

For the rest of this article, I will assume a basic level of Python knowledge and web development.

Let’s get started with our implementation. At the end of this tutorial, we will have an API that allows us to manage an inventory of computer games. If you want to skip ahead to a particular step, you can grab the code from here. Each of the commits is labelled in line with the steps below.

Step 1. Creating our Flask App

Firstly, let’s set up our Flask environment. We’ll use a virtual environment to manage our dependencies.


pip install virtualenv
virtualenv .venv
source .venv/bin/activate
pip install Flask

Now, let’s write some code. In a `main.py` file, let’s initialize our Flask application and add a basic endpoint to list some dummy computer games we’ll add to our inventory.


from flask import Flask, jsonify


app = Flask(__name__)

games = [
    {"id": 1, "title": "Fallout: New Vegas", "price_usd": "4000"},
    {"id": 2, "title": "Tomb Raider", "price_usd": "3500"},
    {"id": 3, "title": "Stray", "price_usd": "1000"},
]


@app.route("/games", methods=["GET"])
def list_games():
    return jsonify(games)

Now, if you browse to http://127.0.0.1:5000/games you should see the list of games returned.

Step 2. Adding Flagsmith

To be able to use Flagsmith in our Python application, we need to initialize the Flagsmith Python SDK. Let’s add the Flagsmith SDK to our virtual environment and write the code to initialize it in our application. 

Add the Flagsmith SDK:


pip install flagsmith

Add the Flagsmith initialisation code:


from flagsmith import Flagsmith

flagsmith = Flagsmith(environment_key=os.environ[“FLAGSMITH_KEY”])

To get this code to work, we’ll need to get an environment key. To do this, you’ll need to create a free account at https://app.flagsmith.com/signup. Once you’ve done that, you can create an organization and a project. As you can see in the screenshots below, I’ve created an organization named Car Sales Inc. and a project named ‘Web Shop’.

Python feature toggles
Python Feature Flagging

Now that we have a project set up, we should see that we have two environments already - Development and Production. For the rest of this article, I’m going to use only the ‘Development’ environment. To get started, we need to create a key to use in our Python application. To do this, navigate to ‘Settings’ under the Development environment and click on ‘Create Server-Side Environment Key’.

Python Feature Flag Library
Feature Flags SDK Python

Once you click ‘Create’, you’ll see the key added to the list. Click the ‘Show’ button and copy the key. (Note: the key should begin with ‘ser.’). Now we can run our application with the following command to get it working with our newly initialized Flagsmith client.


FLAGSMITH_KEY=<your key> flask –app main run

Step 3. Using Python Feature Flag

Now that we have Flagsmith initialized, we can start to use Python feature flagging. Let’s start allowing our customers to purchase the games in our shop! We’ll first create a flag in Flagsmith to enable the shop functionality.

Python Feature Flag Guide

Note that I created this feature via my development environment, however, the feature lives at the project level. The values set when creating a feature are used as the defaults in all environments. 

Now let’s add the logic to our Flask application to support the new feature. To do this, we’ll add a dictionary to maintain our inventory and create a new endpoint to buy a product.


inventory = {
    1: 10,
    2: 13,
    3: 4,
}

@app.route("/games/<int:game_id>/buy", methods=["POST"])
def buy_game(game_id: int):
    flags = flagsmith.get_environment_flags()
    if not flags.is_feature_enabled(SHOP_FLAG_NAME):
        return jsonify({"result": "error", "message": "Shop not yet available!"})

    if game_id not in inventory or inventory[game_id] == 0:
        return jsonify({"result": "error", "message": "Game not in stock!"})

    inventory[game_id] -= 1

    return {"result": "success", "message": "Game bought successfully."}

Note that I’ve pulled out the flag name as a constant at the top of the module as per the following.


SHOP_FLAG_NAME = "shop"

Now if we hit the new endpoint, we should see an error message saying that the shop is not yet available. I’ve added a screenshot below illustrating this using cURL:

python package feature flag

Let’s go ahead and enable the flag now in our development environment and test the new endpoint out.

Toggle Feature Python

Now when we hit the endpoint, we should see a successful response. 

Python Feature Toggling

Step 4. Using Remote Configuration

Now that we’ve seen the functionality to turn features on and off using Flagsmith, we can extend our feature to allow us to remotely configure our shop. Let’s say we want to control the default sort of the games in our list. To do this, we’ll add some JSON metadata to our feature in the Flagsmith interface and use that value in the code. We’ll add a JSON object containing 2 keys to the value of our feature:


{"default_sort_field": "title", "default_sort_direction": "asc"}

Adding this in Flagsmith should look something like this:

Feature Flag Management Python

To use this in our code, we’ll update the list_games view as follows:


@app.route("/games", methods=["GET"])
def list_games():
    flags = flagsmith.get_environment_flags()

    try:
        metadata = json.loads(flags.get_feature_value(SHOP_FLAG_NAME))
        return jsonify(
            sorted(
                games,
                key=lambda i: i[metadata["default_sort_field"]],
                reverse=metadata["default_sort_direction"] == "desc",
            )
        )
    except (TypeError, KeyError) as e:
        pass

    return jsonify(games)

Now our games are listed in the order that we define in Flagsmith. If we want to change it to show the lowest prices first, we can just change the value to:


{"default_sort_field": "price_usd", "default_sort_direction": "asc"}

Step 5. Using Local Evaluation

The implementation above uses remote evaluation mode to retrieve the flags. This means that whenever we make a call to get_environment_flags, we’re making an API call to the Flagsmith API. This is a good thing when we need to make sure that changes made in Flagsmith are reflected immediately in our application, however, it introduces additional latency as we’re making an additional API call whenever a user hits our own endpoint. 

Flagsmith offers a secondary option for this, local evaluation, which means that flags are evaluated by the SDK itself using information that it keeps up to date by polling the Flagsmith API in a separate thread.


More information on this topic can be found in our documentation here. To use local evaluation in our code, all we need to do is add the enable_local_evaluation argument when initializing our Flagsmith client.


flagsmith = Flagsmith(
    environment_key=os.environ["FLAGSMITH_KEY"],
    enable_local_evaluation=True,
)

Here you can see some indicative performance tests when using remote evaluation vs local evaluation.

Remote evaluation:

Toggle Feature in Python

Local evaluation:

Latency Feature Flag Python

You can see that when we enable local evaluation, the latency drops hugely since we’re not making the additional call out to the Flagsmith API. When we enabled local evaluation, we were able to handle 425 requests/sec vs 60 when using remote evaluation. 

Conclusion

We’ve now seen how we can integrate Flagsmith into a basic application. This article focused only on using Flagsmith without identifying users. With identified users, we can start to bring in user segmentation, user overrides, and multivariate features. You can find much more documentation on this topic here.

If you want to start using Flagsmith as your Python feature toggle software- just create your account here or contact us for the on-prem solution.

More Reading

If you like this "Python Feature Flag" guide, you can check out our other guides:

Quote

Subscribe

Learn more about CI/CD, AB Testing and all that great stuff

Success!
We'll keep you up to date with the latest Flagsmith news.
Must be a valid email
Illustration Letter