How to Evaluate Feature Flags in Python

A Python function that evaluates boolean feature flags with user-specific overrides, returning whether a flag is enabled and the reason for the decision.

Easy Python 3.9+ Aug 9, 2026 A/B testing & experimentation 14 views 0 copies

Python code

54 lines
Python 3.9+
import json

def evaluate_feature_flag(feature_name, context, flag_configs):
    """
    Evaluates a boolean feature flag given a context dictionary.

    Args:
        feature_name: The name of the feature flag.
        context: A dictionary of user/request context (e.g., {"user_id": "123"}).
        flag_configs: A dictionary of flag configurations.

    Returns:
        A tuple (enabled, reason) where enabled is bool and reason explains the decision.
    """
    # Flag not found → disabled with a clear reason
    if feature_name not in flag_configs:
        return False, f"flag '{feature_name}' not found"

    config = flag_configs[feature_name]
    enabled = config.get("enabled", False)

    # Check for user-based override rules
    for rule in config.get("overrides", []):
        if rule.get("user_id") == context.get("user_id"):
            return rule["enabled"], f"override matched user_id={context['user_id']}"

    return enabled, "standard evaluation"


if __name__ == "__main__":
    flags = {
        "dark_mode": {"enabled": True, "overrides": [
            {"user_id": "beta_1", "enabled": False}
        ]},
        "new_checkout": {"enabled": False}
    }

    # Simulate mock evaluation for a normal user
    context_normal = {"user_id": "user_123"}
    result_normal = evaluate_feature_flag("dark_mode", context_normal, flags)
    print(f"dark_mode (normal): {result_normal}")

    # Simulate mock evaluation for an overridden user
    context_beta = {"user_id": "beta_1"}
    result_beta = evaluate_feature_flag("dark_mode", context_beta, flags)
    print(f"dark_mode (beta): {result_beta}")

    # Non-existent flag
    result_missing = evaluate_feature_flag("unknown_flag", context_normal, flags)
    print(f"unknown_flag: {result_missing}")

    # Disabled flag
    result_disabled = evaluate_feature_flag("new_checkout", context_normal, flags)
    print(f"new_checkout: {result_disabled}")

Output

stdout
dark_mode (normal): (True, 'standard evaluation')
dark_mode (beta): (False, 'override matched user_id=beta_1')
unknown_flag: (False, "flag 'unknown_flag' not found")
new_checkout: (False, 'standard evaluation')

How it works

The evaluate_feature_flag function first checks if the flag exists in the config dictionary, returning a disabled result with a clear reason if not found. It then reads the enabled value with .get() so missing keys default to False instead of raising an error. User-specific overrides are checked in order, returning the override result immediately when a matching user_id is found — this makes it easy to test beta users or roll back a feature for specific accounts. The function always returns a tuple of (bool, str), which keeps the decision logic transportable and easy to unit test.

Common mistakes

  • Forgetting to handle the case where the flag isn't in the config, causing a KeyError
  • Using `config["enabled"]` directly instead of `.get("enabled", False)` for safe defaults
  • Checking overrides after evaluating the default enabled state, which can accidentally apply overrides to flags that should always be off

Variations

  1. Use percentage-based rollout with `hash(user_id) % 100 < rollout_percentage`
  2. Store configs in a database and cache them in memory for faster lookups

Real-world use cases

  • Rolling out a new UI feature gradually to specific user segments while keeping control over edge-case accounts.
  • A/B testing different checkout flows where a test group gets a new experience and control group stays on the old one.
  • Emergency kill-switch automation — disable a buggy flag for all users instantly without redeploying code.

Sponsored

Run this sample

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

Open editor

More from A/B testing & experimentation

Related tutorials and quizzes for this topic.