Reusable feature flag infrastructure for Django and Python projects (Plug and Play).
Project description
feature-flag-infra
A lightweight, production-ready feature flag infrastructure for Python applications.
Built for clean architecture, progressive rollout, and multi-project reuse.
Supports:
Django (first-class) Any Python project (framework-agnostic) Pluggable providers (DB, Redis, API, etc.) Deterministic rollout (percentage-based) ✨ Why this exists
Most feature flag implementations are:
tightly coupled to a framework hard to reuse across services missing rollout logic not test-friendly
feature-flag-infra solves that by providing:
a clean provider interface a central service layer reusable rollout logic optional Django integration 📦 Installation pip install feature-flag-infra 🧠 Core Concept
Everything revolves around one abstraction:
FeatureFlagService -> FeatureFlagProvider
You plug in your provider (DB, Redis, API), and the service handles usage.
🚀 Quick Start (Framework Agnostic)
- Create a provider from feature_flag_infra.interfaces import FeatureFlagProvider
class InMemoryProvider(FeatureFlagProvider): def init(self): self.flags = { "new_feature": True }
def is_enabled(self, flag, *, user=None, default=False):
return self.flags.get(flag, default)
- Use the service from feature_flag_infra.service import FeatureFlagService
flags = FeatureFlagService(provider=InMemoryProvider())
if flags.enabled("new_feature"): print("Feature is ON") ⚙️ Django Integration
- Add to installed apps INSTALLED_APPS = [ ... "feature_flag_infra.django", ]
- Run migrations python manage.py migrate
- Use in your code from feature_flag_infra.django import get_feature_flags
flags = get_feature_flags()
if flags.enabled("anomaly_detection", user=request.user): # new logic ... 🗃️ Feature Flag Model (Django) FeatureFlag:
- name (unique)
- enabled (bool)
- staff_only (bool)
- rollout_percentage (0–100) 🎯 Rollout Behavior
The library supports deterministic percentage rollout:
user_id + flag_name → hash → bucket (0–99) Example rollout % behavior 0 nobody gets it 50 ~50% of users 100 everyone
This ensures:
consistency (same user always gets same result) safe gradual rollout no randomness issues 🔐 Staff-only Flags if obj.staff_only: return user.is_staff
Use this for:
internal testing admin-only features beta previews 🧠 Caching
Django provider uses caching:
CACHE_TTL = 30 # seconds
This prevents repeated DB hits.
You can plug in:
Redis Memcached local memory 🧩 Extending Providers
You can easily plug in your own provider.
Example: Redis Provider class RedisFlagProvider(FeatureFlagProvider): def init(self, redis_client): self.redis = redis_client
def is_enabled(self, flag, *, user=None, default=False):
value = self.redis.get(flag)
if value is None:
return default
return value == b"1"
🧪 Testing class FakeProvider(FeatureFlagProvider): def is_enabled(self, flag, *, user=None, default=False): return True flags = FeatureFlagService(FakeProvider())
assert flags.enabled("anything") is True 🧱 Design Principles Dependency Inversion (DIP) → provider-based architecture Deterministic rollout → safe progressive delivery Framework isolation → Django is optional Composable → plug into any system Testability first 🔄 Real-world Usage Example: Safe feature release if flags.enabled("new_checkout_flow", user=request.user): return NewCheckoutService.process(...) else: return OldCheckoutService.process(...) Example: Anomaly Detection Toggle if flags.enabled("anomaly_detection", user=request.user): run_detection() 📌 Roadmap Redis provider (first-class) API provider (central flag service) CLI for flag management Admin dashboard improvements Metrics / exposure tracking 🤝 Contributing
PRs are welcome. Focus on:
clean abstractions backward compatibility performance 📄 License
MIT
🧠 Final Note
This library is intentionally minimal but powerful.
It gives you:
control over rollout clean architecture portability across services
Without locking you into a specific ecosystem.
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 feature_flag_infra-0.1.0.tar.gz.
File metadata
- Download URL: feature_flag_infra-0.1.0.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff9081111675896f5765f661c0e08932a8bf64b43addffa1384973b459e740e2
|
|
| MD5 |
651fb6baf4ad96c8fc0c167be1fb6058
|
|
| BLAKE2b-256 |
763aaa44bd267e9ec5010c8627f3911bf61edbcec4304c9ac93bc74f54190982
|
Provenance
The following attestation bundles were made for feature_flag_infra-0.1.0.tar.gz:
Publisher:
cd.yml on 0FFSIDE1/feature_flag_infra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
feature_flag_infra-0.1.0.tar.gz -
Subject digest:
ff9081111675896f5765f661c0e08932a8bf64b43addffa1384973b459e740e2 - Sigstore transparency entry: 1440023019
- Sigstore integration time:
-
Permalink:
0FFSIDE1/feature_flag_infra@76476c4b804c7b2e199601e755a74a16c0b22041 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/0FFSIDE1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cd.yml@76476c4b804c7b2e199601e755a74a16c0b22041 -
Trigger Event:
push
-
Statement type:
File details
Details for the file feature_flag_infra-0.1.0-py3-none-any.whl.
File metadata
- Download URL: feature_flag_infra-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
248a474d6b84e0a46c4a9783e7d21f22ff1b8aca5e2f0611a7ec83552d96d30b
|
|
| MD5 |
157e7e6047bc436f9140cd9212c0df17
|
|
| BLAKE2b-256 |
743c703cd13e1ebead341b0de53dd50fcf91446477dde15252d151901f5058ef
|
Provenance
The following attestation bundles were made for feature_flag_infra-0.1.0-py3-none-any.whl:
Publisher:
cd.yml on 0FFSIDE1/feature_flag_infra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
feature_flag_infra-0.1.0-py3-none-any.whl -
Subject digest:
248a474d6b84e0a46c4a9783e7d21f22ff1b8aca5e2f0611a7ec83552d96d30b - Sigstore transparency entry: 1440023038
- Sigstore integration time:
-
Permalink:
0FFSIDE1/feature_flag_infra@76476c4b804c7b2e199601e755a74a16c0b22041 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/0FFSIDE1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cd.yml@76476c4b804c7b2e199601e755a74a16c0b22041 -
Trigger Event:
push
-
Statement type: