|
| 1 | +--- |
| 2 | +name: flow-code-deprecation |
| 3 | +description: "Use when removing, replacing, or sunsetting features, APIs, modules, or dependencies in any codebase" |
| 4 | +--- |
| 5 | + |
| 6 | +# Deprecation and Migration |
| 7 | + |
| 8 | +## Overview |
| 9 | + |
| 10 | +Code is a liability, not an asset — every line carries ongoing maintenance cost. This skill enforces a disciplined process for deprecating and removing code that no longer earns its keep, ensuring consumers are migrated safely before anything is removed. |
| 11 | + |
| 12 | +## When to Use |
| 13 | + |
| 14 | +- Replacing an old system, API, library, or module with a new one |
| 15 | +- Sunsetting a feature, CLI command, or config option that's no longer needed |
| 16 | +- Consolidating duplicate implementations into a single path |
| 17 | +- Removing dead code that nobody owns but everybody depends on |
| 18 | +- Planning the lifecycle of a new system (deprecation planning starts at design time) |
| 19 | +- Deciding whether to maintain a legacy system or invest in migration |
| 20 | + |
| 21 | +**When NOT to use:** |
| 22 | +- Routine refactoring that doesn't remove public interfaces — use standard refactoring |
| 23 | +- Adding new features alongside old ones without removing anything |
| 24 | +- Version bumps that don't change or remove behavior |
| 25 | +- Bug fixes in legacy code you intend to keep |
| 26 | + |
| 27 | +## The Deprecation Decision |
| 28 | + |
| 29 | +Before deprecating anything, answer these questions: |
| 30 | + |
| 31 | +``` |
| 32 | +1. Does this system still provide unique value? |
| 33 | + → If yes, maintain it. If no, proceed. |
| 34 | +
|
| 35 | +2. How many consumers depend on it? |
| 36 | + → Quantify: grep for imports, check API call logs, review dependency graphs. |
| 37 | +
|
| 38 | +3. Does a replacement exist? |
| 39 | + → If no, BUILD THE REPLACEMENT FIRST. Never deprecate without an alternative. |
| 40 | +
|
| 41 | +4. What's the migration cost per consumer? |
| 42 | + → If automatable (codemod, sed, script), do it yourself (the Churn Rule). |
| 43 | + → If manual and high-effort, weigh against ongoing maintenance cost. |
| 44 | +
|
| 45 | +5. What's the cost of NOT deprecating? |
| 46 | + → Security risk, engineer time, dependency rot, onboarding friction. |
| 47 | +``` |
| 48 | + |
| 49 | +If answers 1=no, 3=yes, and 5 > 4, proceed with deprecation. |
| 50 | + |
| 51 | +## Advisory vs Compulsory Deprecation |
| 52 | + |
| 53 | +| Type | When to Use | Mechanism | |
| 54 | +|------|-------------|-----------| |
| 55 | +| **Advisory** | Old system is stable, migration is optional | Warnings, documentation, nudges. Consumers migrate on their own timeline. | |
| 56 | +| **Compulsory** | Security risk, blocks progress, or maintenance cost is unsustainable | Hard deadline. Old system removed by date X. Provide migration tooling. | |
| 57 | + |
| 58 | +**Default to advisory.** Use compulsory only when risk or cost justifies forcing migration. Compulsory deprecation requires providing migration tooling, documentation, and support — you cannot just announce a deadline. |
| 59 | + |
| 60 | +## Core Process |
| 61 | + |
| 62 | +### Phase 1: Assess Impact |
| 63 | + |
| 64 | +1. **Inventory all consumers** — grep for imports, API calls, config references, CLI invocations. Miss nothing. |
| 65 | +2. **Map the dependency graph** — direct consumers and transitive dependents. Hyrum's Law: with enough users, every observable behavior becomes depended on, including bugs and timing quirks. |
| 66 | +3. **Quantify maintenance cost** — security vulnerabilities, test failures, onboarding friction, dependency update burden. |
| 67 | +4. **Document the assessment:** |
| 68 | + ``` |
| 69 | + Deprecated: <component name> |
| 70 | + Consumers: <count and list> |
| 71 | + Maintenance cost: <specific burden> |
| 72 | + Replacement: <name or "to be built"> |
| 73 | + Migration type: advisory | compulsory |
| 74 | + ``` |
| 75 | + |
| 76 | +### Phase 2: Build the Replacement |
| 77 | + |
| 78 | +**Do NOT announce deprecation until the replacement is production-proven.** |
| 79 | + |
| 80 | +1. **Cover all critical use cases** of the old system |
| 81 | +2. **Write a migration guide** with concrete steps and examples |
| 82 | +3. **Prove it in production** — not just "theoretically better" |
| 83 | +4. **Verify behavioral parity** on edge cases consumers depend on |
| 84 | + |
| 85 | +### Phase 3: Announce and Document |
| 86 | + |
| 87 | +Create a deprecation notice: |
| 88 | + |
| 89 | +``` |
| 90 | +## Deprecation Notice: <ComponentName> |
| 91 | +
|
| 92 | +Status: Deprecated as of <date> |
| 93 | +Replacement: <NewComponent> (see migration guide) |
| 94 | +Removal date: Advisory — no hard deadline | Compulsory — <date> |
| 95 | +Reason: <specific maintenance burden or risk> |
| 96 | +
|
| 97 | +### Migration Steps |
| 98 | +1. Replace <old import/call> with <new import/call> |
| 99 | +2. Update configuration (see examples) |
| 100 | +3. Run migration verification: <command> |
| 101 | +``` |
| 102 | + |
| 103 | +Place notices where consumers will see them: inline warnings, changelogs, documentation headers. |
| 104 | + |
| 105 | +### Phase 4: Migrate Consumers |
| 106 | + |
| 107 | +For each consumer: |
| 108 | + |
| 109 | +1. **Identify all touchpoints** with the deprecated system |
| 110 | +2. **Update to the replacement** — provide codemods or scripts where possible |
| 111 | +3. **Verify behavior matches** — tests, integration checks, manual validation |
| 112 | +4. **Remove references** to the old system |
| 113 | +5. **Confirm no regressions** |
| 114 | + |
| 115 | +**The Churn Rule:** If you own the infrastructure being deprecated, you are responsible for migrating your users — or providing backward-compatible shims. Do not announce deprecation and leave users to figure it out. |
| 116 | + |
| 117 | +### Phase 5: Remove Old Code |
| 118 | + |
| 119 | +Only after all consumers have migrated: |
| 120 | + |
| 121 | +1. **Verify zero active usage** — metrics, logs, dependency analysis, grep |
| 122 | +2. **Remove the code** — implementation, types, exports |
| 123 | +3. **Remove associated artifacts** — tests, documentation, configuration, feature flags |
| 124 | +4. **Remove deprecation notices** — they served their purpose |
| 125 | +5. **Run full verification:** |
| 126 | + ```bash |
| 127 | + $FLOWCTL guard |
| 128 | + ``` |
| 129 | + |
| 130 | +### Phase 6: Verify Clean Removal |
| 131 | + |
| 132 | +1. **Search for orphaned references** — stale imports, dead config keys, broken links in docs |
| 133 | +2. **Run the full test suite** — no failures from missing code |
| 134 | +3. **Check build artifacts** — no phantom exports or dangling symbols |
| 135 | +4. **Confirm documentation is updated** — no references to removed components |
| 136 | + |
| 137 | +For planning migration work across multiple tasks, use `/flow-code:plan`. |
| 138 | + |
| 139 | +## Migration Patterns |
| 140 | + |
| 141 | +### Strangler Pattern |
| 142 | +Run old and new in parallel. Route traffic incrementally from old to new. Remove old when it handles 0%. |
| 143 | + |
| 144 | +### Adapter Pattern |
| 145 | +Wrap old interface around new implementation. Consumers keep using the old interface while the backend migrates underneath. |
| 146 | + |
| 147 | +### Feature Flag Migration |
| 148 | +Use feature flags to switch consumers from old to new one at a time. Roll back instantly if issues arise. |
| 149 | + |
| 150 | +## Zombie Code |
| 151 | + |
| 152 | +Code that nobody owns but everybody depends on. Signs: |
| 153 | +- No commits in 6+ months but active consumers exist |
| 154 | +- No assigned maintainer |
| 155 | +- Failing tests nobody fixes |
| 156 | +- Dependencies with known vulnerabilities nobody updates |
| 157 | + |
| 158 | +**Response:** Either assign an owner and maintain it, or deprecate it with a concrete migration plan. Zombie code cannot stay in limbo. |
| 159 | + |
| 160 | +## Common Rationalizations |
| 161 | + |
| 162 | +| Excuse | Reality | |
| 163 | +|--------|---------| |
| 164 | +| "It still works, why remove it?" | Working code without maintenance accumulates security debt and complexity. Cost grows silently until it's a crisis. | |
| 165 | +| "Someone might need it later" | If needed later, it can be rebuilt with better design. Keeping unused code "just in case" costs more than rebuilding. | |
| 166 | +| "No one uses this anymore" | Did you verify that with grep, metrics, and logs? Undocumented consumers are the norm, not the exception. | |
| 167 | +| "We can remove it later" | Later never comes. Every month you delay, more consumers may adopt the deprecated path. | |
| 168 | +| "Breaking changes are fine for a major version" | A major version bump does not excuse removing things without migration paths. Semver is a signal, not a license to break users. | |
| 169 | +| "The migration is too expensive" | Compare migration cost to 2-3 years of ongoing maintenance. Migration is almost always cheaper long-term. | |
| 170 | +| "Users will migrate on their own" | They won't. Provide tooling, documentation, and support — or do the migration yourself (the Churn Rule). | |
| 171 | +| "We can maintain both indefinitely" | Two systems doing the same thing means double the maintenance, testing, documentation, and onboarding cost. | |
| 172 | + |
| 173 | +## Red Flags |
| 174 | + |
| 175 | +- Deprecating a system with no replacement available or proven |
| 176 | +- Deprecation announcement with no migration guide, tooling, or timeline |
| 177 | +- "Soft" deprecation that has been advisory for months or years with no progress |
| 178 | +- Removing code without verifying zero active consumers first |
| 179 | +- New features added to a system already marked deprecated (invest in the replacement instead) |
| 180 | +- Zombie code with no owner and active consumers left in limbo |
| 181 | +- Deprecation without quantifying current usage |
| 182 | + |
| 183 | +## Verification |
| 184 | + |
| 185 | +After completing a deprecation cycle, confirm: |
| 186 | + |
| 187 | +- [ ] Deprecation decision documented with consumer count, maintenance cost, and replacement name |
| 188 | +- [ ] Replacement is production-proven and covers all critical use cases |
| 189 | +- [ ] Migration guide exists with concrete steps, examples, and verification commands |
| 190 | +- [ ] All active consumers migrated (verified by grep, metrics, or logs — not assumption) |
| 191 | +- [ ] Old code, tests, documentation, and configuration fully removed |
| 192 | +- [ ] No orphaned references to the deprecated system remain in the codebase |
| 193 | +- [ ] `$FLOWCTL guard` passes after removal |
| 194 | +- [ ] Deprecation notices removed (they served their purpose) |
0 commit comments