SkillByAIOpen interactive version →

Lesson 7 / 25

Feature Flags, Percent Rollouts and Kill Switches

Stable bucketing and an off button.

Deterministic buckets

A feature flag decides at runtime whether a user gets the AI feature. Percent rollouts should be deterministic: hash the user id with the feature name into a bucket from 0 to 99 and enable the feature if the bucket is below the rollout percentage. Users then keep a consistent experience, and raising the percentage only adds users. A kill switch turns the feature off for everyone instantly, falling back to the non-AI path. Flag services (LaunchDarkly, Unleash, open-source flagd, cloud config services) provide this with audit logs.

Control exposure without deploying

Flags let you choose who sees the feature, change it instantly and switch it off in seconds.

Figure 3.1 — Flags, cohorts and config.

Hash-based percent rollout and kill switch, run

I ran this with Python 3 (scipy 1.18.1 where imported) on example numbers, not data from a real product. Across 10,000 users, rollouts of 1%, 10% and 50% enable 0.9%, 10.1% and 50.0%. Everyone enabled at 10% is still enabled at 50%, and turning on the kill switch enables nobody.

import hashlib
def bucket(user_id, feature):          # stable 0-99 bucket per user and feature
    h = hashlib.sha256(f"{feature}:{user_id}".encode()).hexdigest()
    return int(h[:8], 16) % 100
def enabled(user_id, feature, percent, kill_switch=False):
    return (not kill_switch) and bucket(user_id, feature) < percent
users = [f"user-{i}" for i in range(10000)]
for pct in [1, 10, 50]:
    share = sum(enabled(u, "ai-summary", pct) for u in users) / len(users)
    print(f"rollout {pct:>2}% -> {share:.1%} of 10,000 users enabled")
on_at_10 = {u for u in users if enabled(u, "ai-summary", 10)}
on_at_50 = {u for u in users if enabled(u, "ai-summary", 50)}
print("everyone enabled at 10% stays enabled at 50%:", on_at_10 <= on_at_50)
print("kill switch on ->", sum(enabled(u, "ai-summary", 50, kill_switch=True) for u in users), "users enabled")

Output:

rollout  1% -> 0.9% of 10,000 users enabled
rollout 10% -> 10.1% of 10,000 users enabled
rollout 50% -> 50.0% of 10,000 users enabled
everyone enabled at 10% stays enabled at 50%: True
kill switch on -> 0 users enabled

Test the kill switch before launch

Flip it in staging and in production during dogfooding; an untested off switch is not a safety mechanism.

Quick check: Why hash the user id for percent rollouts instead of choosing randomly per request?

  • Each user gets a consistent experience and raising the percentage only adds users
  • Hashing makes the model faster
  • Random choice is illegal
  • Hashing reduces token cost
Answer

Each user gets a consistent experience and raising the percentage only adds users — Stable buckets avoid flip-flopping.