Feature Flags: Deploy with Confidence, Release with Control
March 12, 2026 · 9 min · 1731 words · Rob Washington
Table of Contents
Deployment and release are not the same thing. Feature flags let you deploy code to production without releasing it to users. Here’s how to implement them without creating technical debt.
# models.pyclassFeatureFlag(Base):__tablename__="feature_flags"name=Column(String,primary_key=True)enabled=Column(Boolean,default=False)rollout_percentage=Column(Integer,default=0)enabled_for_users=Column(ARRAY(String),default=[])# flags.pyfromfunctoolsimportlru_cacheimporttime_cache={}_cache_ttl=60# secondsdefget_flag(name:str)->FeatureFlag:now=time.time()ifnamein_cacheand_cache[name]['expires']>now:return_cache[name]['flag']flag=db.query(FeatureFlag).filter_by(name=name).first()_cache[name]={'flag':flag,'expires':now+_cache_ttl}returnflagdefis_enabled(name:str,user_id:str=None)->bool:flag=get_flag(name)ifnotflag:returnFalse# Check user allowlistifuser_idanduser_idin(flag.enabled_for_usersor[]):returnTrue# Check percentage rolloutifflag.rollout_percentage>0:# Consistent hashing so user always gets same resulthash_val=hash(f"{name}:{user_id}")%100returnhash_val<flag.rollout_percentagereturnflag.enabled
fromlaunchdarkly_clientimportLDClientclient=LDClient("sdk-key-xxx")# Basic checkifclient.variation("new-checkout",user,False):returnnew_checkout_flow()# With user contextuser={"key":"user-123","email":"alice@example.com","custom":{"plan":"premium","country":"US"}}# Targeting rules can use these attributesshow_feature=client.variation("premium-feature",user,False)
fromUnleashClientimportUnleashClientclient=UnleashClient(url="http://unleash:4242/api",app_name="my-app",custom_headers={"Authorization":"token"})client.initialize_client()# Usageifclient.is_enabled("new-checkout"):returnnew_checkout_flow()# With contextcontext={"userId":"user-123","properties":{"plan":"premium"}}ifclient.is_enabled("premium-feature",context):returnpremium_flow()
defpercentage_rollout(flag_name:str,user_id:str,percentage:int)->bool:"""Consistent percentage rollout using hash."""# Same user always gets same result for same flaghash_input=f"{flag_name}:{user_id}"hash_value=int(hashlib.md5(hash_input.encode()).hexdigest(),16)%100returnhash_value<percentage
# Bad: Flags accumulate foreverifis_enabled("feature_q1_2023"):# Still here in 2026?...# Good: Include expirationclassFeatureFlag:expires_at:datetime# Alert if flag still exists after this# CI checkdefcheck_expired_flags():expired=db.query(FeatureFlag).filter(FeatureFlag.expires_at<datetime.now()).all()ifexpired:raiseException(f"Expired flags need cleanup: {expired}")
# test_checkout.pyimportpytest@pytest.fixturedefenable_new_checkout(monkeypatch):monkeypatch.setenv("FEATURE_NEW_CHECKOUT","true")@pytest.fixturedefdisable_new_checkout(monkeypatch):monkeypatch.setenv("FEATURE_NEW_CHECKOUT","false")deftest_new_checkout_flow(enable_new_checkout):result=checkout()assertresult.template=="new_checkout.html"deftest_legacy_checkout_flow(disable_new_checkout):result=checkout()assertresult.template=="legacy_checkout.html"# Test both paths always@pytest.mark.parametrize("flag_enabled",[True,False])deftest_checkout_completes(flag_enabled,monkeypatch):monkeypatch.setenv("FEATURE_NEW_CHECKOUT",str(flag_enabled).lower())result=checkout()assertresult.status=="success"