Codegen has been used in production for multi-million line codebases to automatically delete “dead” (rolled-out) feature flags. This guide will walk you through analyzing feature flag usage and safely removing rolled out flags.

Every codebase does feature flags differently. This guide shows common techniques and syntax but likely requires adaptation to codebase-specific circumstances.

Analyzing Feature Flag Usage

Before removing a feature flag, it’s important to analyze its usage across the codebase. Codegen provides tools to help identify where and how feature flags are used.

For Python Codebases

For Python codebases using a FeatureFlags class pattern like so:

class FeatureFlags:
    FEATURE_1 = False
    FEATURE_2 = True

You can use Class.get_attribute(…) and Attribute.usages to analyze the coverage of your flags, like so:

feature_flag_usage = {}
feature_flag_class = codebase.get_class('FeatureFlag')

if feature_flag_class:
    # Initialize usage count for all attributes
    for attr in feature_flag_class.attributes:
        feature_flag_usage[attr.name] = 0
    
    # Get all usages of the FeatureFlag class
    for usage in feature_flag_class.usages:
        usage_source = usage.usage_symbol.source if hasattr(usage, 'usage_symbol') else str(usage)
        for flag_name in feature_flag_usage.keys():
            if f"FeatureFlag.{flag_name}" in usage_source:
                feature_flag_usage[flag_name] += 1

    sorted_flags = sorted(feature_flag_usage.items(), key=lambda x: x[1], reverse=True)

    print("Feature Flag Usage Table:")
    print("-------------------------")
    print(f"{'Feature Flag':<30} | {'Usage Count':<12}")
    print("-" * 45)
    for flag, count in sorted_flags:
        print(f"{flag:<30} | {count:<12}")

    print(f"\nTotal feature flags: {len(sorted_flags)}")
else:
    print("❗ FeatureFlag enum not found in the codebase")

This will output a table showing all feature flags and their usage counts, helping identify which flags are candidates for removal.

Learn more about Attributes and tracking usages here

Removing Rolled Out Flags

Once you’ve identified a flag that’s ready to be removed, Codegen can help safely delete it and its associated code paths.

This primarily leverages Codegen’s API for reduction conditions

Python Example

For Python codebases, here’s how to remove a feature flag and its usages:

flag_name = "FEATURE_TO_REMOVE"

# Get the feature flag variable
feature_flag_file = codebase.get_file("app/utils/feature_flags.py")
flag_class = feature_flag_file.get_class("FeatureFlag")

# Check if the flag exists
flag_var = flag_class.get_attribute(flag_name)
if not flag_var:
    print(f'No such flag: {flag_name}')
    return

# Remove all usages of the feature flag
for usage in flag_var.usages:
    if isinstance(usage.parent, IfBlockStatement):
        # For if statements, reduce the condition to True
        usage.parent.reduce_condition(True)
    elif isinstance(usage.parent, WithStatement):
        # For with statements, keep the code block
        usage.parent.code_block.unwrap()
    else:
        # For other cases, remove the usage
        usage.remove()

# Remove the flag definition
flag_var.remove()

# Commit changes
codebase.commit()

React/TypeScript Example

For React applications using a hooks-based feature flag system:

feature_flag_name = "NEW_UI_ENABLED"
target_value = True  # The value to reduce the flag to

print(f'Removing feature flag: {feature_flag_name}')

# 1. Remove from configuration
config_file = codebase.get_file("src/featureFlags/config.ts")
feature_flag_config = config_file.get_symbol("FEATURE_FLAG_CONFIG").value
if feature_flag_name in feature_flag_config.keys():
    feature_flag_config.pop(feature_flag_name)
    print('✅ Removed from feature flag config')

# 2. Find and reduce all hook usages
hook = codebase.get_function("useFeatureFlag")
for usage in hook.usages:
    fcall = usage.match
    if isinstance(fcall, FunctionCall):
        # Check if this usage is for our target flag
        first_arg = fcall.args[0].value
        if isinstance(first_arg, String) and first_arg.content == feature_flag_name:
            print(f'Reducing in: {fcall.parent_symbol.name}')
            # This automatically handles:
            # - Ternary expressions: flag ? <New /> : <Old />
            # - If statements: if (flag) { ... }
            # - Conditional rendering: {flag && <Component />}
            fcall.reduce_condition(target_value)

# 3. Commit changes
codebase.commit()

This will:

  1. Remove the feature flag from the configuration
  2. Find all usages of the useFeatureFlag hook for this flag
  3. Automatically reduce any conditional logic using the flag
  4. Handle common React patterns like ternaries and conditional rendering

Was this page helpful?