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
- Fetch flag from local in-memory cache (never DB directly).
- Flag missing or
enabled=False→ returnDEFAULT_VALUE. rollout_percentage == 100→ returnTrue.user.idintargeted_user_ids→ returnTrue.- User attributes don't satisfy
conditions→ returnFalse. - 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
- On startup (
AppConfig.ready), all flags are loaded from PostgreSQL into a thread-safe in-memory dict. - A background daemon thread subscribes to the Redis channel
featureflow:flags. - Every time a flag is saved or deleted, a
post_save/post_deletesignal publishes the updated payload to that channel. - All workers receive the message and update their local caches atomically via
threading.RLock. - 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbe67239fc7b75c3ed37cdac64e88ad94dfa89bdba72ed5c5a67700b56b83ecd
|
|
| MD5 |
da2b078a1325e349b07fec4d91293538
|
|
| BLAKE2b-256 |
6520af39a1a781dc940d50ca54102172738cb9dcd97c68699d7c145b3220517c
|
File details
Details for the file django_featureflow-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_featureflow-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc7165f1f0f9c21214e23c469bee8dacf2ba16e585ebb3a15d37fd9804cd8218
|
|
| MD5 |
4f771de409ce9e189accce5fe35720fb
|
|
| BLAKE2b-256 |
df716b21e769be2d0a482e28ab28fb16a893e04f2b3ed7c7facba7019c9c77ba
|