Set Cookies for Feature Flags in Django

What are we trying to do#

Let's assume you know about feature flags and are ready to use them in your project. We need some method to persist decision paths for our user; something has to keep track if `FeatureA` is enabled and `FeatureB` is disabled. There are several options for tracking and toggling features. The spectrum of when these flags are set ranges from build time to run time. You can hard-code variables in code (

FeatureA = True
). On the other side of the spectrum, you can decouple releases from deployments. There are hosted feature flipper services like LaunchDarkly that offer a console to activate flags.

For this tutorial let's use a persistence method that's somewhere in the middle. Let's set a cookie in a user's browser that we check to toggle feature flags. For this tutorial we'll create a view with Django and Django REST Framework. This view sets a cookie that's useful for features and redirects a user to a variable URL.

Defining Our View#

A great part about cookie-based feature flags is that we can deploy code and deliver value to users in production. Let's create an endpoint that sets a cookie for a user. The purpose of this cookie is to enable a feature. We'll also redirect the user to a URL we choose; presumably the URL where they'll see the flagged feature in action.

# flags/views.py

from django.shortcuts import redirect
from rest_framework import serializers

FEATURES = {"new-home-page": False}


class FeatureFlagException(Exception):
    pass


class CookieFlagSerializer(serializers.Serializer):
    feature_name = serializers.CharField()
    enable = serializers.ChoiceField(choices=("true", "false"))
    duration = serializers.IntegerField(min_value=0, max_value=365 * 24 * 3600)
    redirect_url = serializers.URLField()

Let's break this down.

FEATURES
is a dictionary where keys are feature names and values are the features default state: on or off mapping to
True
or
False
. While we don't use the default on/off state in this post, you can see it in action in this follow-up post.

We use the `python±class CookieFlagSerializer` to validate the attributes of our feature flag. The attributes are few, but useful:

  • feature_name
    - What we're calling the feature. Matches a key in
    FEATURES
    .
  • enable
    - Allows us to toggle a feature on and off.
  • duration
    - Seconds until the cookie expires and no longer affects the user.
  • redirect_url
    - We'll redirect the user to this URL after the cookie is set.

Setting a cookie#

We set the cookie in a basic Django view with a few guards around feature flags. We use the serializer we defined above to validate the flag parameters:

# flags/views.py (continued)
def set_cookie_flag_view(request, feature_name):
    serializer = CookieFlagSerializer(
        data={
            "feature_name": feature_name,
            "enable": request.GET.get("enable"),
            "duration": request.GET.get("duration"),
            "redirect_url": request.GET.get("redirect_url"),
        }
    )
    serializer.is_valid(raise_exception=True)

    feature_name = serializer.validated_data["feature_name"]
    if feature_name not in FEATURES:
        raise FeatureFlagException(f"{feature_name} is not a valid feature flag.")

    cookie_name = f"features.{feature_name}"
    cookie_value = serializer.validated_data["enable"]
    cookie_duration = serializer.validated_data["duration"]
    redirect_url = serializer.validated_data["redirect_url"]

    response = redirect(redirect_url)
    response.set_cookie(cookie_name, cookie_value, max_age=cookie_duration)
    return response

This, along with a URL configuration like the following are all you need to to create a view that's useful for cookie-based feature flags:

# flags/urls.py
from django.urls import path

from .views import set_cookie_flag_view

path("features/<slug:feature_name>/", set_cookie_flag_view)

Now I can go to a URL like the following and have a feature flag cookie dropped in my browser and be redirected to the flagged URL (we're using the AD home page as an example):

https://accelerate.delivery/features/new-home-page/?enable=true&duration=86400&redirect_url=https://accelerate.delivery
You can respond to this cookie in front-end and back-end code. You can toggle individual lines of code or entire views. If you're ready for the next, simple step, read my article: Toggling Views with Cookies in Django