Remove flags you’re done with.
Every release flag is temporary. A short routine keeps your code and your config free of switches nobody flips.
1
Temporary or permanent
Give each setting a lifecycle. temporary is for release flags and experiments that should go once they are at 100% or 0%. permanent is for kill switches, plan entitlements and remote settings that stay. Set an owner too, so someone gets asked. Filter the flag list by either.
2
Find the ones that are done
A temporary flag is done when it serves one plain value in every environment, with no rules or split, and nobody has touched it for a while. The flag list shows every environment's state at a glance; this script lists the candidates:
import { Flags } from "@productcraft/flags";
const flags = new Flags(); // PRODUCTCRAFT_API_KEY + PRODUCTCRAFT_WORKSPACE_ID
declare const configId: string;
declare const productionId: string;
// Temporary flags that serve one plain value in every environment, with
// no rules, unchanged for 30 days: candidates to remove from the code.
const cutoff = Date.now() - 30 * 24 * 3600 * 1000;
for await (const row of flags.configs.environments.values.list(configId, productionId, { include: "states" })) {
const states = Object.values(row.states ?? {}); // the compact state in every environment
const first = states[0];
const settled = first !== undefined && states.every((st) => !st.has_rules && st.value === first.value);
if (row.setting.lifecycle === "temporary" && settled && Date.parse(row.value.updated_at) < cutoff) {
console.log(`${row.setting.key}: serves ${String(first.value)} everywhere since ${row.value.updated_at}`);
}
}3
Code first, then Flags
- Remove every read of the flag from your code, keeping the branch it serves, and deploy.
- Delete the flag in Flags. Do it in this order: an app still reading a deleted flag gets its default (reason
ERROR,FLAG_NOT_FOUND), which may be the old behaviour.
Prerequisites and segments that point at the flag block the delete (409 SETTING_IN_USE); the flag page lists them. The delete is kept in History with your note.
import { Flags } from "@productcraft/flags";
const flags = new Flags(); // PRODUCTCRAFT_API_KEY + PRODUCTCRAFT_WORKSPACE_ID
declare const settingId: string;
const setting = await flags.settings.retrieve(settingId);
// Prerequisites and segments that point at it block the delete (409).
console.log(setting.dependents);
await flags.settings.delete(settingId, { note: "new_checkout shipped to 100%; code path removed in #812" });