{
    "slug": "feature_toggle_types",
    "term": "Feature Toggle Types",
    "category": "devops",
    "difficulty": "intermediate",
    "short": "Release toggles, ops toggles, experiment toggles, and permission toggles — each with different lifespans, owners, and removal disciplines.",
    "long": "Pete Hodgent's taxonomy: Release Toggles gate incomplete features for trunk-based development — short-lived (days to weeks), removed once released. Ops Toggles control operational behaviour (kill switch for a feature under load) — potentially long-lived, owned by ops. Experiment Toggles (A/B tests) route cohorts to different code paths — medium lifetime, data-driven removal. Permission Toggles give specific users/tenants access to premium features — long-lived, permanent in the codebase. Each type has different implications: release toggles create technical debt if not cleaned up; experiment toggles require statistical significance before decision; permission toggles need admin UI. PHP libraries: flagsmith/flagsmith-php-client, unleash/client, or a simple database-backed implementation.",
    "aliases": [
        "feature flag types",
        "release toggle",
        "experiment toggle",
        "ops toggle"
    ],
    "tags": [
        "devops",
        "deployment",
        "feature-flags"
    ],
    "misconception": "All feature flags are the same and should be managed the same way. Release toggles (short-lived, deployment control), experiment toggles (A/B testing, medium lifespan), ops toggles (circuit breakers, long-lived), and permission toggles (per-user features) have different lifecycles and should be managed separately.",
    "why_it_matters": "Different toggle types have different lifecycles — release toggles are temporary, ops toggles are permanent, experiment toggles are short-lived. Mixing them creates unmanaged flag debt.",
    "common_mistakes": [
        "Treating all feature flags the same — release flags should be removed after launch; ops flags should not.",
        "No flag inventory or ownership — flags accumulate with no one knowing if they are safe to remove.",
        "Toggling features mid-transaction — partial feature activation can leave data in inconsistent states.",
        "Hard-coding toggle checks deep in domain logic instead of at the entry point — toggles belong at boundaries."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "continuous_deployment",
        "canary_release",
        "css_nesting",
        "trunk_based_development"
    ],
    "prerequisites": [
        "feature_flag",
        "canary_release",
        "blue_green_deployment"
    ],
    "refs": [
        "https://martinfowler.com/articles/feature-toggles.html"
    ],
    "bad_code": "// Feature flag with no expiry or owner — permanent flag debt:\nif (config('features.new_checkout')) {\n    // 'Temporary' flag from 18 months ago — never removed\n    // No one knows if false branch is still tested\n    // No ticket, no owner, no removal plan\n}",
    "good_code": "// Release toggle — hide incomplete feature from users\n\\$flags->isEnabled('new_billing_ui', \\$user);\n\n// Experiment toggle — A/B test\n\\$variant = \\$flags->getVariant('checkout_flow', \\$user); // 'control' or 'treatment'\n\n// Ops toggle — kill switch for a live feature under load\nif (!\\$flags->isEnabled('recommendation_engine')) {\n    return []; // disable when it's hammering the DB\n}\n\n// Permission toggle — role-based feature access\nif (\\$flags->isEnabled('beta_dashboard', \\$user)) { ... } // only for beta users\n\n// Implementation approaches:\n// 1. Config file / env var — simplest, needs deploy to change\n// 2. Database row — live changes, no deploy\n// 3. Feature flag service (LaunchDarkly, Flagsmith, Unleash) — targeting rules",
    "quick_fix": "Match toggle type to its lifecycle: release toggles are short-lived (deploy then clean up), ops toggles are long-lived (circuit breaker), experiment toggles have a defined test period",
    "severity": "medium",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/feature_toggle_types",
        "html_url": "https://codeclaritylab.com/glossary/feature_toggle_types",
        "json_url": "https://codeclaritylab.com/glossary/feature_toggle_types.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Feature Toggle Types](https://codeclaritylab.com/glossary/feature_toggle_types) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/feature_toggle_types"
            }
        }
    }
}