Why an Agent Leaves a Feature Flag Turned On
Quick answer: A feature flag is a temporary release control, not a permanent part of the code. Once the feature is verified and stable, the flag should either be removed so the code paths merge, or be explicitly converted into a documented long-term setting. When an agent turns the flag on and walks away, the temporary switch accumulates as technical debt, and the disabled branch slowly becomes untested dead code.
Why the flag stays on
Getting the feature live is the task, and with the flag enabled the feature works, so the agent reads that as done. Removing the flag means deleting a branch and re-testing the merged path, which carries risk and is rarely written into the task. The agent has no built-in notion that a flag carries an expiration, and in a long session the flag was added early, so later turns never mention cleaning it up.
This separates it from two related failures. A feature verified behind a local flag that ships off by default never reaches production at all, and a config flag added to dodge a choice is a product decision being postponed. Here the feature does ship; the problem is the switch meant to control the rollout is left in place after the rollout is finished. For how this fits the broader work of running coding agents well, see the AI coding agent guide.
What a permanently-on flag costs
The off branch stops being exercised. It still compiles and gets reviewed, but no test runs through it, so when someone later flips the flag or tries to remove it, the path has quietly drifted out of correctness. As these flags pile up, the configuration matrix grows faster than any test suite can cover, and an old flag switched off by mistake can take a working feature down. New contributors also cannot tell which flags are still safe to toggle, so every switch becomes a guess.
The states a flag can be in
Not every flag should be deleted, but each one needs a declared type and a next action.
| Flag type | Why it exists | What happens after verification |
|---|---|---|
| Release / rollout flag | Gradual rollout, kill switch | Remove once stable at full rollout |
| Experiment flag | A/B test of a behavior | Keep the winner, delete the flag and losing path |
| Operational setting | Long-lived control such as a limit | Document it, assign an owner, keep it |
| Forgotten flag, always on | No clear owner or end date | Audit and remove in a cleanup change |
How to keep flags from becoming permanent
Write the type, owner, and cleanup condition when the flag is first added, not months later. A flag without a removal date is the one most likely to stay. Make removal part of the definition of done, either in the same change once rollout is confirmed or in a tracked cleanup task that follows immediately.
Audit the flag list on a regular cadence. A flag that has been on for all traffic for weeks with no toggle is a removal candidate. Before deleting it, confirm the off path receives no traffic, then remove the flag and the dead branch together and run the main path through the test suite.
Powerduck's code review flags files with no resolved incoming references and identical content, which helps locate the dead branches a stale flag leaves behind, while staying honest that no incoming reference does not prove a file is safe to delete.
Frequently asked questions
Aren't feature flags meant for long-term control? Some operational settings are, and those should be documented and owned. A rollout or experiment flag is temporary by design; leaving it on forever is the failure, not the intent.
How do I know an on flag is safe to remove? Confirm it has been fully rolled out, the off path has no traffic, and the behavior is now the default. Then remove the flag and the unused branch in one change.
Does removing a flag risk the working feature? The risk comes from the off branch drifting, not from the deletion. Merge the paths deliberately, keep the verified on behavior as the only path, and test that path.
The bottom line
A feature flag is a tool with an expiration date. Turning it on is not the end of the job; once the rollout is proven, either delete it and merge the code or formally keep it as a named, owned setting. Every flag with no owner and no end date is a future incident waiting for a toggle.