Skip to main content

Realtime distributed feature flag engine for Django

Project description

FeatureFlow

A realtime, distributed feature flag engine for Django. Flags are evaluated in-process from a local in-memory cache, kept consistent across all workers via Redis pub/sub. Zero network hops on the hot path.


Requirements

  • Python 3.11+
  • Django 5.2+
  • PostgreSQL 14+ (uses ArrayField)
  • Redis 6+

Installation

pip install -r requirements.txt

Add to INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "rest_framework",
    "rest_framework.authtoken",
    "featureflow.apps.FeatureFlowConfig",
]

Mount the API in your root URLconf:

from django.urls import include, path

urlpatterns = [
    path("api/", include("featureflow.urls")),
]

Configuration

Add a FEATUREFLOW block to your Django settings:

FEATUREFLOW = {
    "REDIS_URL": "redis://localhost:6379",   # Redis connection string
    "ENV": "production",                     # Default environment label
    "CACHE_TTL": 300,                        # Seconds before a full cache refresh
    "DEFAULT_VALUE": False,                  # Returned when a flag key is missing
}

Database setup

# Create the PostgreSQL database
createdb featureflow

# Run migrations
python manage.py migrate

Usage

Python SDK

from featureflow import feature_enabled, enable, disable

# Basic check (no user context)
if feature_enabled("dark-mode"):
    ...

# Per-user evaluation with conditions + rollout
if feature_enabled("new-checkout", user=request.user):
    ...

# Pass extra context attributes not on the user object
if feature_enabled("beta-search", user=request.user, context={"country": "NG"}):
    ...

# Programmatically flip flags
enable("dark-mode")    # sets enabled=True, rollout_percentage=100
disable("dark-mode")   # sets enabled=False

Evaluation order

  1. Fetch flag from local in-memory cache (never DB directly).
  2. Flag missing or enabled=False → return DEFAULT_VALUE.
  3. rollout_percentage == 100 → return True.
  4. user.id in targeted_user_ids → return True.
  5. User attributes don't satisfy conditions → return False.
  6. HMAC-based deterministic bucket: hmac(flag_key, user_id) % 100 < rollout_percentage.

REST API

All endpoints require authentication (Token or Session).

Method URL Description
POST /api/flags/ Create a flag
GET /api/flags/ List all flags (?environment=production)
GET /api/flags/<key>/ Retrieve a flag
PATCH /api/flags/<key>/ Partial update
DELETE /api/flags/<key>/ Delete
POST /api/flags/<key>/enable/ Enable + set 100% rollout
POST /api/flags/<key>/disable/ Disable
GET /api/flags/<key>/audit/ Audit log for this flag

Create a flag

curl -X POST http://localhost:8000/api/flags/ \
  -H "Authorization: Token <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "dark-mode",
    "name": "Dark Mode",
    "enabled": true,
    "rollout_percentage": 50,
    "conditions": {"subscription": "premium"},
    "targeted_user_ids": [1, 2, 3],
    "environment": "production"
  }'

Obtain an auth token

python manage.py drf_create_token <username>

Flag model fields

Field Type Description
key slug Unique identifier used in code
name string Human-readable label
description string Optional notes
enabled bool Master switch
rollout_percentage 0–100 % of users who see the feature
conditions JSON User attribute filters (all must match)
targeted_user_ids int[] Users who always get the feature
environment enum development / staging / production

How caching and pub/sub work

  1. On startup (AppConfig.ready), all flags are loaded from PostgreSQL into a thread-safe in-memory dict.
  2. A background daemon thread subscribes to the Redis channel featureflow:flags.
  3. Every time a flag is saved or deleted, a post_save / post_delete signal publishes the updated payload to that channel.
  4. All workers receive the message and update their local caches atomically via threading.RLock.
  5. If Redis is unavailable, each worker continues serving the last known cached state with no interruption.

Running tests

# Create the test database
createdb featureflow_test

# Run the full suite
pytest

Tests mock Redis pub/sub interactions and require a live PostgreSQL connection for API and model tests.


Django Admin

Visit /admin/ to manage flags and view immutable audit logs. The audit log admin is read-only.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_featureflow-0.1.0.tar.gz (12.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_featureflow-0.1.0-py3-none-any.whl (13.7 kB view details)

Uploaded Python 3

File details

Details for the file django_featureflow-0.1.0.tar.gz.

File metadata

  • Download URL: django_featureflow-0.1.0.tar.gz
  • Upload date:
  • Size: 12.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for django_featureflow-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dbe67239fc7b75c3ed37cdac64e88ad94dfa89bdba72ed5c5a67700b56b83ecd
MD5 da2b078a1325e349b07fec4d91293538
BLAKE2b-256 6520af39a1a781dc940d50ca54102172738cb9dcd97c68699d7c145b3220517c

See more details on using hashes here.

File details

Details for the file django_featureflow-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_featureflow-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bc7165f1f0f9c21214e23c469bee8dacf2ba16e585ebb3a15d37fd9804cd8218
MD5 4f771de409ce9e189accce5fe35720fb
BLAKE2b-256 df716b21e769be2d0a482e28ab28fb16a893e04f2b3ed7c7facba7019c9c77ba

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page