-
Notifications
You must be signed in to change notification settings - Fork 1
Feature Flags
Armin RAD edited this page Dec 16, 2025
·
1 revision
A/B testing and feature management with Statsig
Feature flags enable:
- Gradual rollouts - Release features to subsets
- A/B testing - Test variations
- Kill switches - Disable features instantly
- User targeting - Target specific users/segments
- Analytics integration - Track feature impact
Provider: Statsig
STATSIG_SDK_KEY=secret-xxx
STATSIG_ENVIRONMENT=production # or staging, developmentfrom src.services.statsig_service import check_feature_gate
# Check if feature enabled for user
enabled = await check_feature_gate(
user_id="user_123",
gate_name="new_pricing_ui"
)
if enabled:
# Show new UI
return render_new_ui()
else:
# Show old UI
return render_old_ui()config = await get_feature_config(
user_id="user_123",
config_name="pricing_tiers"
)
# Use config values
tier_prices = config.get("prices", default_prices)GET /features/gate/{gate_name}
Response:
{
"enabled": true,
"gate_name": "new_pricing_ui",
"user_id": "user_123"
}GET /features/config/{config_name}
Response:
{
"config_name": "pricing_tiers",
"value": {
"free": 0,
"basic": 10,
"pro": 50
}
}# Statsig Dashboard:
# Gate: "new_dashboard"
# Rule: % rollout = 10%
if check_gate(user_id, "new_dashboard"):
return new_dashboard()
else:
return old_dashboard()10% of users see new dashboard.
# Gate: "beta_features"
# Rule: User email ends with @company.com
if check_gate(user_id, "beta_features"):
show_beta_features()# Experiment: "pricing_experiment"
# Variants: control, variant_a, variant_b
variant = get_experiment(user_id, "pricing_experiment")
if variant == "variant_a":
price = 9.99
elif variant == "variant_b":
price = 14.99
else: # control
price = 12.99# Emergency disable
if not check_gate(user_id, "enable_payments"):
return {"error": "Payments temporarily disabled"}Toggle off instantly in dashboard.
- Go to Statsig Dashboard
- Navigate to Feature Gates
- Click Create
- Set name:
new_pricing_ui - Add rules:
- All users: 0% (default off)
- Email contains "@admin.com": 100%
- Random: 10% rollout
- Save
- Navigate to Dynamic Configs
- Click Create
- Set name:
pricing_config - Add JSON value:
{
"tiers": ["free", "basic", "pro"],
"prices": [0, 10, 50]
}- Save
- Navigate to Experiments
- Click Create
- Set name:
button_color_test - Define variants:
- Control (blue)
- Variant A (green)
- Variant B (red)
- Set allocation: 33% each
- Start experiment
import { useGate } from 'statsig-react';
function PricingPage() {
const { value: newPricing } = useGate('new_pricing_ui');
return newPricing ? <NewPricing /> : <OldPricing />;
}from fastapi import Depends
from src.services.statsig_service import StatsigService
@app.get("/pricing")
async def get_pricing(
user_id: int = Depends(get_current_user),
statsig: StatsigService = Depends()
):
if await statsig.check_gate(user_id, "new_pricing"):
return new_pricing_structure
return old_pricing_structureLocation: src/services/statsig_service.py
from statsig import statsig
class StatsigService:
def __init__(self):
statsig.initialize(os.getenv("STATSIG_SDK_KEY"))
async def check_gate(self, user_id: str, gate: str) -> bool:
user = {"userID": user_id}
return statsig.check_gate(user, gate)
async def get_config(self, user_id: str, config: str):
user = {"userID": user_id}
return statsig.get_config(user, config)
async def log_event(self, user_id: str, event: str, metadata: dict):
user = {"userID": user_id}
statsig.log_event(user, event, metadata=metadata)# Rule: userID in ["user_1", "user_2", "user_3"]# Rule: email ends with "@company.com"user = {
"userID": "123",
"custom": {
"plan": "pro",
"country": "US",
"signup_date": "2024-01-01"
}
}
statsig.check_gate(user, "us_only_feature")
# Rule: country == "US"# Rule: Random % = 25%
# 25% of users see featurefrom src.services.statsig_service import log_event
# Log feature usage
await log_event(
user_id="user_123",
event="feature_used",
metadata={
"feature": "new_dashboard",
"action": "clicked_button"
}
)Statsig automatically tracks:
- Exposure: Users who saw experiment
- Conversions: Users who completed goal
- Lift: % improvement over control
- Start small: 5-10% rollout initially
- Monitor metrics: Watch for errors/performance
-
Use descriptive names:
new_pricing_v2_2024 - Document gates: What they control
- Clean up old gates: Remove unused flags
- Test both paths: Ensure on/off works
- Set defaults: Fail-safe if Statsig down
Cause: SDK key wrong or gate doesn't exist
Solution:
- Verify
STATSIG_SDK_KEYin .env - Check gate name spelling
- Verify gate exists in dashboard
Cause: Cache not refreshed
Solution:
# Force refresh
statsig.shutdown()
statsig.initialize(sdk_key)Cause: User doesn't match targeting rules
Solution: Check rules in dashboard, verify user attributes
STATSIG_SDK_KEY=secret-xxx
STATSIG_ENVIRONMENT=production
STATSIG_LOG_LEVEL=infoimport statsig
statsig.initialize(
sdk_key=os.getenv("STATSIG_SDK_KEY"),
options={
"environment": {"tier": "production"},
"disable_diagnostics": False
}
)- Statsig Docs
- Analytics System - Event tracking
Last Updated: December 2024 Status: Production Ready
Reading Path (start here, in order)
- Conceptual Model
- Stability Definition
- Conceptual Model Features
- Features
- Delta Report
- Features-Acceptance-Criteria
Testing
Security & Access
Billing
Monitoring
Features
Providers
Operations
Data References