How to Mock a Feature Flag Rollout Percentage in Python

Simulate a percentage-based feature flag rollout by hashing a user ID to deterministically enable features for a subset of users.

Easy Python 3.9+ Aug 9, 2026 Production deployment patterns 11 views 0 copies

Python code

22 lines
Python 3.9+
import random
from dataclasses import dataclass


@dataclass
class FeatureFlag:
    name: str
    rollout_percentage: int


def is_feature_enabled(feature_flag: FeatureFlag, user_id: str) -> bool:
    hashed_id = hash(user_id) % 100
    return hashed_id < feature_flag.rollout_percentage


if __name__ == "__main__":
    flag = FeatureFlag(name="new_checkout", rollout_percentage=25)
    users = ["alice", "bob", "carol", "dave", "eve", "frank", "grace", "heidi"]

    for user in users:
        enabled = is_feature_enabled(flag, user)
        print(f"User {user:8s} -> feature {'ENABLED' if enabled else 'disabled'}")

Output

stdout
User alice   -> feature disabled
User bob     -> feature disabled
User carol   -> feature ENABLED
User dave    -> feature disabled
User eve     -> feature disabled
User frank   -> feature disabled
User grace   -> feature ENABLED
User heidi   -> feature disabled

How it works

The hash(user_id) call produces a deterministic integer for the same string within a single Python run, and % 100 maps it to a 0-99 range. Comparing that value against the rollout percentage gives a stable 25% chance that any given user sees the feature enabled. Using a hash (rather than random) means the same user consistently gets the same result, which keeps the rollout predictable across requests. This simple approach works well for local testing and shadows real-world feature flag services like LaunchDarkly.

Common mistakes

  • Using `random.randint` or `random.random` which gives different results each call — breaking determinism for the same user
  • Forgetting that Python's `hash()` is salted per process so results differ across runs — use a stable hash like `hashlib.md5` in production
  • Not wrapping the modulo, which can produce negative values on some platforms unless you use `abs()` or `& 0xffffffff`

Variations

  1. Use `hashlib.md5(user_id.encode()).hexdigest()` to get a stable hash across runs and platforms for production use
  2. Implement with `random.Random(user_id).randint(0, 99)` for a slower but run-independent deterministic result

Real-world use cases

  • Testing a new checkout flow with a staged rollout to a small percentage of production users before full release.
  • Shadow-deploying an internal dashboard feature where a stable subset of employees see the new UI first.
  • Simulating gradual feature adoption in a demo or staging environment without a paid feature-flag service.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Production deployment patterns

Related tutorials and quizzes for this topic.