🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Build an AI Feature Flag Risk Analyzer with Claude API

Feature flags accumulate silently until nobody remembers what half of them do or whether they're safe to remove. Build a tool that analyzes your feature flag inventory against actual usage and code references with Claude API to flag stale, risky, or safe-to-delete flags.

Shubham4 min read
Share:Tweet

Feature flag systems (LaunchDarkly, Unleash, Flagsmith, or a homegrown one) accumulate flags faster than teams clean them up — a flag rolled out to 100% six months ago is still evaluated on every request, still adds cognitive load to anyone reading the code, and might be silently load-bearing in a way nobody remembers. This tool cross-references flag state, usage, and code to tell you which flags are safe to remove.

Setup

bash
pip install anthropic requests

Flag Inventory Collector

python
import anthropic
import requests
import subprocess
import re
 
client = anthropic.Anthropic()
 
 
def get_flag_inventory(api_key: str) -> list[dict]:
    """Example for LaunchDarkly — adapt for your flag provider's API."""
    resp = requests.get(
        "https://app.launchdarkly.com/api/v2/flags/my-project",
        headers={"Authorization": api_key}
    )
    flags = resp.json()["items"]
    return [{
        "key": f["key"],
        "name": f["name"],
        "created_date": f["creationDate"],
        "temporary": f.get("temporary", False),
        "environments": f.get("environments", {}),
    } for f in flags]
 
 
def get_flag_evaluation_stats(flag_key: str, api_key: str, days: int = 30) -> dict:
    """Pull rollout percentage and evaluation counts — a flag stuck at
    100% rollout for months with no variation being served is a strong
    signal it should just be removed from the code."""
    resp = requests.get(
        f"https://app.launchdarkly.com/api/v2/flags/my-project/{flag_key}/status",
        headers={"Authorization": api_key}
    )
    return resp.json()

Code Reference Scanner

python
def find_code_references(flag_key: str, repo_path: str) -> list[dict]:
    """Find every place in the codebase this flag is actually referenced."""
    result = subprocess.run(
        ["grep", "-rn", flag_key, repo_path, "--include=*.py", "--include=*.ts", "--include=*.js"],
        capture_output=True, text=True
    )
    references = []
    for line in result.stdout.splitlines():
        parts = line.split(":", 2)
        if len(parts) == 3:
            references.append({"file": parts[0], "line": parts[1], "code": parts[2].strip()})
    return references

Risk Analysis with Claude

python
import json
 
ANALYZE_PROMPT = """Analyze this feature flag for cleanup risk.
 
Flag: {flag_key}
Created: {created_date}
Marked temporary: {temporary}
Current rollout state per environment: {environments}
Evaluation stats (last {days} days): {eval_stats}
 
Code references found:
{code_references}
 
Determine:
1. Is this flag safe to remove entirely (100% rolled out everywhere for
   months, code always takes the "on" branch, no A/B test still running)?
2. Is this flag stale but risky to touch (references exist but the logic
   is tangled — removing needs careful review, not a mechanical delete)?
3. Is this flag actively in use for legitimate ongoing purposes (kill switch,
   active experiment, gradual rollout still in progress)?
 
Respond with ONLY valid JSON:
{{"verdict": "safe_to_remove" | "stale_needs_review" | "actively_used",
  "reasoning": "...", "cleanup_complexity": "simple" | "moderate" | "complex" | null}}"""
 
 
def analyze_flag_risk(flag: dict, eval_stats: dict, code_references: list, days: int = 30) -> dict:
    response = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=500,
        messages=[{
            "role": "user",
            "content": ANALYZE_PROMPT.format(
                flag_key=flag["key"], created_date=flag["created_date"],
                temporary=flag["temporary"], environments=flag["environments"],
                eval_stats=eval_stats, code_references=code_references, days=days,
            )
        }]
    )
    text = response.content[0].text.strip()
    if text.startswith("```"):
        text = text.split("```")[1].replace("json", "", 1).strip()
    return json.loads(text)

Generating a Cleanup Report

python
def generate_cleanup_report(repo_path: str, ld_api_key: str) -> str:
    flags = get_flag_inventory(ld_api_key)
    report = ["# Feature Flag Cleanup Report\n"]
    safe_count = 0
 
    for flag in flags:
        eval_stats = get_flag_evaluation_stats(flag["key"], ld_api_key)
        code_refs = find_code_references(flag["key"], repo_path)
        analysis = analyze_flag_risk(flag, eval_stats, code_refs)
 
        if analysis["verdict"] == "safe_to_remove":
            safe_count += 1
            report.append(f"## ✅ {flag['key']} — Safe to remove ({analysis['cleanup_complexity']})")
            report.append(f"{analysis['reasoning']}")
            report.append(f"References: {len(code_refs)} locations\n")
        elif analysis["verdict"] == "stale_needs_review":
            report.append(f"## ⚠️ {flag['key']} — Stale, needs manual review")
            report.append(f"{analysis['reasoning']}\n")
 
    report.insert(1, f"**{safe_count} flags safe to remove** out of {len(flags)} total\n")
    return "\n".join(report)

Usage

bash
python flag_analyzer.py --repo ./myapp --output cleanup-report.md
 
# Feature Flag Cleanup Report
# 8 flags safe to remove out of 34 total
#
# ✅ new-checkout-flow — Safe to remove (simple)
# 100% rolled out in all environments since 2026-02-15 (5+ months),
# code takes the "on" branch unconditionally in all 3 references, no
# A/B test infrastructure detected around it.
# References: 3 locations
#
# ⚠️ payments-retry-logic — Stale, needs manual review
# 100% rolled out for 4 months, but code references show complex
# conditional logic intertwined with error handling — a mechanical
# removal risks changing retry behavior in a way that needs careful testing.

Why This Stays a Report, Not an Auto-Delete

Removing flag code, even for a flag that's clearly at 100% rollout, means editing application logic — that always deserves a human-reviewed PR, never an automated deletion. The value here is turning "which of our 34 flags are safe to clean up" from a manual audit nobody has time for into a prioritized list someone can actually work through.


More AI DevOps tooling? Read our Build AI YAML diff explainer with Claude API and Build AI PR description generator with Claude API.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments