Features App¶
Feature flags for gradual rollouts, A/B testing, and feature management.
Overview¶
The features app provides:
- Enable/disable features per user, organization, or globally
- Feature flag caching for performance
- A/B testing support
- Gradual feature rollout
- Feature metrics and tracking
Quick Start¶
Check Feature Flags¶
from htk.apps.features.utils import get_feature_flag
# Check if feature is enabled for user
if get_feature_flag('new_dashboard', user):
return render(request, 'new_dashboard.html')
else:
return render(request, 'old_dashboard.html')
# Check global feature
if get_feature_flag('maintenance_mode'):
return redirect('/maintenance/')
Create Feature Flags¶
from htk.apps.features.models import FeatureFlag
# Global flag
flag = FeatureFlag.objects.create(
name='new_checkout',
description='New checkout flow',
is_active=True
)
# User-specific flag
flag.enable_for_user(user)
flag.disable_for_user(other_user)
# Percentage-based rollout
flag.set_percentage_rollout(10) # 10% of users
A/B Testing¶
from htk.apps.features.utils import assign_variant
# Assign user to variant
variant = assign_variant('new_ui_test', user)
if variant == 'control':
template = 'ui/control.html'
else:
template = 'ui/new.html'
return render(request, template)
Models¶
FeatureFlag- Main feature flag modelFeatureFlagUser- User-specific overridesFeatureFlagOrganization- Organization-specific settings
Caching¶
Feature flags are automatically cached:
from htk.apps.features.cachekeys import FeatureFlagCache
cache = FeatureFlagCache('feature_name')
cache.invalidate_cache() # Refresh when flag changes
Best Practices¶
- Use descriptive names -
new_checkout_v2, notflag_1 - Document purpose - Add description when creating
- Monitor adoption - Track which users have which features
- Gradual rollout - Use percentage-based rollout before full launch
- Clean up old flags - Remove completed experiments
Typical Flow¶
- Create flag (disabled by default)
- Enable for internal testing
- Enable for percentage of users
- Monitor metrics
- Roll out to 100% or disable
- Remove flag code after full rollout
Integration Examples¶
In Templates¶
{% if feature_flag 'new_dashboard' %}
<!-- New dashboard content -->
{% else %}
<!-- Legacy dashboard content -->
{% endif %}
In Tests¶
def test_new_feature(self):
flag = FeatureFlag.objects.create(name='test_feature', is_active=True)
flag.enable_for_user(self.user)
response = self.client.get('/dashboard/')
self.assertContains(response, 'New feature')