# Flag lifecycle management

Feature flags are temporary by nature unless explicitly designated as permanent. Without a lifecycle process, temporary flags accumulate as technical debt. This page covers how to classify flags, track their status, and clean them up.

## Mark temporary vs. permanent at creation

Only temporary flags are subject to stale detection and archive-readiness checks. Classify flags at creation time:

| Temporary | Permanent |
| --- | --- |
| Release flags | Kill switches |
| Experiment flags | Operational flags |
| Migration flags | Entitlement flags |

## Document the cleanup plan up front

Use the flag description to record:

- Purpose and expected behavior of each variation
- Responsible party or team
- Expected removal date
- Side effects or dependencies on other flags or services

Create the cleanup pull request at the same time as the feature pull request. The cleanup PR removes the flag checks and the dead code path, ready to merge once the feature is fully rolled out.

## Include flag archival in your definition of done

A feature is not done when it ships. It is done when the temporary flag is archived.

## Understand flag status signals

LaunchDarkly tracks flag status per environment:

| Status | Meaning |
| --- | --- |
| New | Created fewer than 7 days ago, never evaluated |
| Active | Being evaluated with multiple variations, recent configuration changes, or the flag is toggled off |
| Launched | Evaluated in the past 7 days, serving only one variation, no configuration changes in 7 days, and toggled on |
| Inactive | No evaluations for at least 7 days |

## Understand cleanup stages

At the project level, LaunchDarkly surfaces two cleanup stages:

**Ready for code removal:** The flag meets all of these criteria:

- Temporary flag
- "Launched" status in all critical environments
- 30 or more days old
- Not a prerequisite for another flag

**Ready to archive:** The flag meets all of these criteria:

- Temporary flag
- "Inactive" status in all critical environments
- 30 or more days old
- No code references
- Not a prerequisite for another flag

## Set up code references

The `ld-find-code-refs` utility scans your codebase and reports flag usage back to LaunchDarkly. It is available as a GitHub Action, GitLab CI job, or Docker container.

When all code references to a flag are removed and the scanning tool reruns, LaunchDarkly creates an extinction event confirming removal. A flag with no code references can then meet the criteria for the "Ready to archive" cleanup stage.

## Customize lifecycle settings

In **Project Settings** > **Lifecycle settings**, configure the criteria for when LaunchDarkly considers a flag ready to archive:

- Minimum flag age
- How long targeting must be unchanged before code removal
- How long evaluations must be absent before archiving
- Whether the flag must not be a prerequisite
- Whether the flag must be serving one variation
- Whether the flag must be temporary

## Build cleanup into your workflow

Flag cleanup works best when it is part of the team's existing process, not a separate initiative. Choose a strategy that fits your team's cadence:

**Attach a cleanup ticket to every feature epic:** When a team creates an epic for a flagged feature, add a cleanup ticket to the same epic. The ticket covers removing the flag checks, deleting the dead code path, and archiving the flag in LaunchDarkly. The epic is not closed until the cleanup ticket is done. Use flag links to connect the flag to the ticket in Jira, Trello, or other tracking systems.

**Dedicate time for flag cleanup days:** Schedule a quarterly cleanup day where teams review the "Needs code removal" and "Ready to archive" lists and work through the backlog. This works well for organizations where cleanup tickets tend to get deprioritized in favor of new work.

**Assign cleanup to on-call or rotation:** Some teams add flag cleanup to their on-call or bug rotation responsibilities. Engineers on rotation pick up flags from the cleanup list between other tasks.

**Schedule regular reviews:** Add a recurring calendar event for monthly or quarterly flag reviews. Walk through the "Needs code removal" and "Ready to archive" lists as a team during this session. Use the review to create cleanup tickets, reassign orphaned flags, and track progress against the previous review.

## Use the Cleanup shortcut, custom shortcuts and filters

The built-in **Cleanup** shortcut appears in the left sidenav and surfaces flags that are ready to archive. You can also create additional ones to cover other flag types or combinations. Filter the Flags list by lifecycle stage, maintainer, or tag, then click the **bolt** icon above the list to save the filtered view as a new shortcut. Other ideas may be shortcuts for "Needs code removal" and "Ready to archive" so the lists are one click away when you need them.

Shortcuts are personal. Only you can see the shortcuts you create.

## Use Views to organize flags by team

Views are different from shortcuts. A view is a project-level grouping of flags and segments that is visible to everyone in your account. Use views to organize flags by team or domain, for example "frontend," "backend," or "payments." A flag can belong to more than one view.

Views also support access control. You can restrict access to a view so that only certain members or teams can see and modify the flags linked to it. This lets you scale to thousands of flags in a single project while keeping each team focused on the flags they own.

Use views alongside lifecycle management to assign flag ownership. When a team owns a view, they are responsible for the flags in it, including cleanup.

<div class="page-metadata"><table class="page-metadata-table" aria-label="Page metadata"><thead><tr><th scope="col">Last modified</th><th scope="col">Last reviewed</th><th scope="col">Review due</th></tr></thead><tbody><tr><td><time datetime="2026-04-29">2026-04-29</time></td><td></td><td></td></tr><tr><td>Last commit: <a href="https://github.com/launchdarkly-labs/ps-flag-book/commit/2e92061">2e92061</a></td><td></td><td></td></tr></tbody></table></div>