Feature Flags
feature_flags# Feature Flags
Overview
The Feature Flags module provides a powerful system for dynamically enabling or disabling features in your application at runtime, without requiring a code deployment. This is an essential tool for continuous delivery, A/B testing, and safely rolling out new functionality.
Key Features
- Multiple Backends: Supports fetching flags from a local configuration dictionary, Redis, or Consul KV.
- Declarative Usage: Protect an entire function or code path with the simple
@feature_enableddecorator. - Contextual Evaluation: Flags can be evaluated based on the current
ExecutionContext(e.g., enable a feature only for a specifictenant_id). - Multivariate Flags: Supports variants, which are flags that can return a string, number, or JSON object instead of just true/false.
How It Works
The system is orchestrated by the FeatureFlagFactory, which creates a provider instance based on your configuration. The primary way to interact with the system is through two utility functions:
- is_feature_enabled(flag_key): Checks if a boolean flag is active.
- get_feature_variant(flag_key): Retrieves the value of a multivariate flag.
For convenience, the @feature_enabled decorator wraps this logic, protecting an entire function.
Usage Example
from nala.athomic.control import feature_enabled, is_feature_enabled, get_feature_variant
from nala.athomic.context import context_vars
# --- Using the decorator ---
@feature_enabled(flag_key="new-dashboard-feature", context_kwargs=["tenant_id"])
async def show_new_dashboard(tenant_id: str):
# This code will only run if the "new-dashboard-feature" is enabled.
# The check can be contextual based on the tenant_id.
return {"dashboard": "v2"}
# --- Using the utility functions ---
async def get_user_limit() -> int:
# Get a variant value, with a default of 100
limit = await get_feature_variant("user-concurrent-limit", default=100)
return limit
Configuration
[default.control.feature_flags]
enabled = true
# The primary backend to fetch flags from.
backend = "consul"
# TTL in seconds for caching flags from external providers (Redis, Consul).
cache_ttl_seconds = 60
[default.control.feature_flags.provider]
backend = "consul"
# The base path in Consul KV where flags are stored.
kv_prefix = "config/flags"