Status: proposed Date: 2026-05-19
Multiple agents working on related features in the same area must serialize — one waits for the other to merge. Incomplete features either block the main branch or require long-lived branches that diverge. SRE needs kill switches without reverting commits.
Feature flags enable trunk-based development where incomplete work merges safely behind toggles, and concurrent contributors avoid blocking each other.
| Situation | Use a flag? |
|---|---|
| Feature spans multiple PRs, incomplete state is unsafe | Yes |
| Two contributors touch the same module for different purposes | Yes |
| SRE needs a kill switch for a new capability | Yes |
| Simple refactor with no behavioral change | No |
| Bug fix | No |
| One-PR feature, complete on merge | No |
- Every flag has an owner (the issue that introduced it)
- Every flag has an expiration (the issue/PR that removes it)
- Flags without a removal plan are rejected in review
- Planners decide which features get flags (issue/RFC level)
- Implementors add/use flags in code (PR level)
- SRE/operators toggle flags in production (runtime level)
- No self-approval — the person who introduces a flag cannot approve its removal
- Proposed — issue identifies the need for a flag
- Introduced — PR adds the flag (default: off)
- Active — feature behind flag is in development
- Verified — feature complete, flag toggled on in testing
- Permanent — flag removed, feature is always-on (or removed entirely)
Each flag must track:
| Field | Required | Source |
|---|---|---|
| Flag name | Yes | Code constant |
| Purpose / linked issue | Yes | Issue reference |
| First merge date | Yes | Auto from git log |
| Max lifetime | Yes | Declared at creation (default: 4 weeks) |
| Expected removal date | Yes | first_merge + max_lifetime |
| Actual removal date | — | Auto when flag deleted |
| Days active | — | Computed |
Flags must be removed within the declared max lifetime (default: 4 weeks) of the feature being verified. The max lifetime can be overridden per-flag with justification in the issue. Stale flags are treated as technical debt and surfaced in periodic reviews.
Flags MUST be resolvable at synth time for infrastructure flags and at runtime for behavior flags. The specific storage mechanism (CDK context, DynamoDB, SSM Parameter Store, env vars) is context-dependent and follows from this split — it is not prescribed by this ADR.
- (+) Concurrent work proceeds without blocking
- (+) Trunk-based development: main stays deployable
- (+) SRE can disable features without code changes
- (+) Partial features merge safely
- (-) Flag management overhead
- (-) Combinatorial testing complexity if many flags exist simultaneously
- (!) Maximum lifetime must be enforced or flags accumulate indefinitely
- Issue #137 — full RFC with open questions on mechanism (CDK context vs. DynamoDB vs. env vars)
- ADR-003 — governance (flag introduction requires approval)
- ADR-005 — feedback loop (reviewer may flag-gate a feature during review)