Option
HeimHeim Skill Entwicklertools deprecation-and-migration

deprecation-and-migration

addyosmani/agent-skills addyosmani/agent-skills

Bietet eine Anleitung für die schrittweise Ablösung alter Systeme, APIs oder Funktionen und die Umstellung der Nutzer auf Ersatzlösungen, einschließlich Entscheidungsrahmen, Migrationsmuster und Strategien zur Stilllegung.

...Alle erweitern
22
Zeit aktualisiert 3. September 2026

Veraltete Funktionen und Migration

Überblick

Code ist eine Belastung, kein Gewinn. Jede Codezeile verursacht laufende Wartungskosten – Fehler müssen behoben, Abhängigkeiten aktualisiert, Sicherheitspatches installiert und neue Entwickler eingearbeitet werden. Die Stilllegung ist die Disziplin, Code zu entfernen, der sich nicht mehr bezahlt macht, und die Migration ist der Prozess, Nutzer sicher vom Alten zum Neuen zu führen.

Die meisten Entwicklungsabteilungen sind gut darin, Dinge zu entwickeln. Nur wenige sind gut darin, sie wieder zu entfernen. Diese Kompetenz schließt diese Lücke.

Wann ist der Einsatz sinnvoll

  • Ersetzen eines alten Systems, einer alten API oder einer alten Bibliothek durch ein neues
  • Ein Feature auslaufen lassen, das nicht mehr benötigt wird
  • Konsolidierung doppelter Implementierungen
  • Entfernen von „toten“ Codeabschnitten, für die niemand verantwortlich ist, auf die aber alle angewiesen sind
  • Planung des Lebenszyklus eines neuen Systems (die Planung der Auslaufphase beginnt bereits in der Entwurfsphase)
  • Entscheidung, ob ein Altsystem weitergewartet oder in eine Migration investiert werden soll

Grundprinzipien

Code ist eine Belastung

Jede Codezeile verursacht laufende Kosten: Sie erfordert Tests, Dokumentation, Sicherheitspatches, Aktualisierungen von Abhängigkeiten und geistigen Aufwand für alle, die damit arbeiten. Der Wert von Code liegt in der Funktionalität, die er bereitstellt, nicht im Code selbst. Wenn dieselbe Funktionalität mit weniger Code, geringerer Komplexität oder besseren Abstraktionen bereitgestellt werden kann, sollte der alte Code entfernt werden.

Hyrums Gesetz erschwert die Entfernung

Bei einer ausreichenden Anzahl von Nutzern wird jedes beobachtbare Verhalten zur Voraussetzung – einschließlich Fehlern, zeitlichen Eigenheiten und undokumentierten Nebeneffekten. Deshalb erfordert die Abkündigung eine aktive Migration und nicht nur eine Ankündigung. Nutzer können nicht „einfach umsteigen“, wenn sie auf Verhaltensweisen angewiesen sind, die der Ersatz nicht nachbildet.

Die Planung der Ausmusterung beginnt bereits in der Entwurfsphase

Wenn Sie etwas Neues entwickeln, fragen Sie sich: „Wie würden wir das in drei Jahren entfernen?“ Systeme, die mit sauberen Schnittstellen, Feature-Flags und minimaler Oberfläche entworfen wurden, lassen sich leichter auslaufen lassen als Systeme, bei denen überall Implementierungsdetails durchscheinen.

Die Entscheidung zur Ausmusterung

Bevor Sie etwas auslaufen lassen, beantworten Sie diese Fragen:

1. Bietet dieses System noch einen einzigartigen Mehrwert?
   → Wenn ja, behalte es bei. Wenn nein, fahre fort.

2. Wie viele Nutzer/Kunden sind davon abhängig?
   → Quantifizieren Sie den Umfang der Migration.

3. Gibt es einen Ersatz?
   → Falls nein, entwickeln Sie zuerst den Ersatz. Stellen Sie nichts ohne Alternative ein.

4. Wie hoch sind die Migrationskosten für jeden Kunden?
   → Wenn die Automatisierung trivial ist, führen Sie sie durch. Wenn sie manuell und aufwendig ist, wägen Sie die Kosten gegen die Wartungskosten ab.

5. Wie hoch sind die laufenden Wartungskosten, wenn das System NICHT ausgemustert wird?
   → Sicherheitsrisiko, Zeitaufwand für Entwickler, Opportunitätskosten aufgrund der Komplexität.

Zwingende vs. empfohlene Auslaufphase

Typ Anwendungsfall Mechanismus
Empfehlung Die Migration ist optional, das alte System ist stabil Warnungen, Dokumentation, sanfte Aufforderungen. Benutzer migrieren nach ihrem eigenen Zeitplan.
Obligatorisch Das alte System weist Sicherheitslücken auf, behindert den Fortschritt oder die Wartungskosten sind nicht mehr tragbar Feste Frist. Das alte System wird bis zum Datum X abgeschaltet. Migrationswerkzeuge bereitstellen.

Standardmäßig „empfohlen“. Verwenden Sie „obligatorisch“ nur, wenn die Wartungskosten oder das Risiko eine erzwungene Migration rechtfertigen. Eine obligatorische Ablösung erfordert die Bereitstellung von Migrationswerkzeugen, Dokumentation und Support – es reicht nicht aus, lediglich eine Frist anzukündigen.

Der Migrationsprozess

Schritt 1: Entwicklung des Ersatzsystems

Führen Sie keine Auslaufphase ohne funktionierende Alternative durch. Der Ersatz muss:

  • alle kritischen Anwendungsfälle des alten Systems abdecken
  • über Dokumentation und Migrationsanleitungen verfügen
  • sich im Produktivbetrieb bewährt haben (nicht nur „theoretisch besser“ sein)

Schritt 2: Ankündigung und Dokumentation

## Veraltungshinweis: OldService

**Status:** Ab dem 01.03.2025 veraltet
**Ersatz:** NewService (siehe Migrationsanleitung unten)
**Entfernungsdatum:** Empfehlung – noch keine feste Frist
**Grund:** OldService erfordert manuelle Skalierung und bietet keine Observability.
            NewService erledigt beides automatisch.

### Migrationsanleitung
1. Ersetzen Sie `import { client } from 'old-service'` durch `import { client } from 'new-service'`
2. Aktualisieren Sie die Konfiguration (siehe Beispiele unten)
3. Führen Sie das Skript zur Migrationsüberprüfung aus: `npx migrate-check`

Schritt 3: Schrittweise Migration

Migrieren Sie die Verbraucher nacheinander und nicht alle auf einmal. Für jeden Verbraucher:

1. Identifizieren Sie alle Berührungspunkte mit dem veralteten System
2. Aktualisieren Sie die Nutzung auf den Ersatz
3. Überprüfen Sie, ob das Verhalten übereinstimmt (Tests, Integrationsprüfungen)
4. Entfernen Sie Verweise auf das alte System
5. Vergewissern Sie sich, dass keine Regressionen vorliegen

Die „Churn“-Regel: Wenn Sie Eigentümer der veralteten Infrastruktur sind, sind Sie dafür verantwortlich, Ihre Nutzer zu migrieren – oder rückwärtskompatible Updates bereitzustellen, die keine Migration erfordern. Kündigen Sie die Veralterung nicht an und überlassen Sie es nicht den Nutzern, sich selbst zurechtzufinden.

Schritt 4: Das alte System entfernen

Erst nachdem alle Nutzer migriert sind:

1. Überprüfen Sie, dass keine aktive Nutzung mehr vorliegt (Metriken, Protokolle, Abhängigkeitsanalyse)
2. Entfernen Sie den Code
3. Entfernen Sie zugehörige Tests, Dokumentation und Konfiguration
4. Entfernen Sie die Veraltungshinweise
5. Feiern Sie – das Entfernen von Code ist eine Leistung

Migrationsmuster

Strangler-Muster

Betreiben Sie das alte und das neue System parallel. Leiten Sie den Datenverkehr schrittweise vom alten zum neuen System um. Wenn das alte System 0 % des Datenverkehrs verarbeitet, entfernen Sie es.

Phase 1: Das neue System verarbeitet 0 %, das alte 100 %
Phase 2: Das neue System verarbeitet 10 % (Canary)
Phase 3: Das neue System verarbeitet 50 %
Phase 4: Das neue System verarbeitet 100 %, das alte System ist inaktiv
Phase 5: Das alte System entfernen

Adapter-Muster

Erstellen Sie einen Adapter, der Aufrufe von der alten Schnittstelle in die neue Implementierung übersetzt. Die Verbraucher nutzen weiterhin die alte Schnittstelle, während Sie das Backend migrieren.

// Adapter: alte Schnittstelle, neue Implementierung
class LegacyTaskService implements OldTaskAPI {
  constructor(private newService: NewTaskService) {}

  // Alte Methodensignatur, delegiert an die neue Implementierung
  getTask(id: number): OldTask {
    const task = this.newService.findById(String(id));
    return this.toOldFormat(task);
  }
}

Migration mithilfe von Feature-Flags

Verwenden Sie Feature-Flags, um die Verbraucher nacheinander vom alten auf das neue System umzustellen:

function getTaskService(userId: string): TaskService {
  if (featureFlags.isEnabled('new-task-service', { userId })) {
    return new NewTaskService();
  }
  return new LegacyTaskService();
}

Zombie-Code

Zombie-Code ist Code, für den niemand verantwortlich ist, auf den aber alle angewiesen sind. Er wird nicht aktiv gepflegt, hat keinen klaren Verantwortlichen und sammelt Sicherheitslücken und Kompatibilitätsprobleme an. Anzeichen:

  • Keine Commits seit mehr als 6 Monaten, obwohl es aktive Nutzer gibt
  • Kein zugewiesener Betreuer oder kein zugewiesenes Team
  • Fehlgeschlagene Tests, die niemand behebt
  • Abhängigkeiten mit bekannten Schwachstellen, die niemand aktualisiert
  • Dokumentation, die auf Systeme verweist, die nicht mehr existieren

Antwort: Entweder einen Verantwortlichen zuweisen und das Projekt ordnungsgemäß betreuen oder es mit einem konkreten Migrationsplan als veraltet kennzeichnen. Zombie-Code darf nicht in der Schwebe bleiben – entweder wird in ihn investiert oder er wird entfernt.

Häufige Rechtfertigungen

Rechtfertigung Realität
„Es funktioniert immer noch, warum sollte man es entfernen?“ Funktionierender Code, der von niemandem gewartet wird, führt zu Sicherheitslücken und zunehmender Komplexität. Die Wartungskosten steigen unbemerkt an.
„Vielleicht braucht es jemand später noch.“ Wenn es später gebraucht wird, kann es neu erstellt werden. Ungenutzten Code „nur für den Fall“ aufzubewahren, kostet mehr als eine Neuerstellung.
„Die Migration ist zu teuer“ Vergleichen Sie die Migrationskosten mit den laufenden Wartungskosten über einen Zeitraum von 2–3 Jahren. Langfristig ist eine Migration in der Regel günstiger.
„Wir werden ihn auslaufen lassen, sobald das neue System fertig ist“ Die Planung der Ausmusterung beginnt bereits in der Entwurfsphase. Bis das neue System fertig ist, werden Sie andere Prioritäten haben. Planen Sie jetzt.
„Die Nutzer werden von selbst migrieren“ Das werden sie nicht. Stellen Sie Tools, Dokumentation und Anreize bereit – oder führen Sie die Migration selbst durch (die Churn-Regel).
„Wir können beide Systeme auf unbestimmte Zeit weiterbetreiben.“ Zwei Systeme, die dasselbe leisten, bedeuten doppelte Kosten für Wartung, Tests, Dokumentation und Einarbeitung.

Warnsignale

  • Veraltete Systeme, für die kein Ersatz verfügbar ist
  • Ankündigungen zur Einstellung ohne Migrationswerkzeuge oder Dokumentation
  • „Weiche“ Auslaufankündigungen, die seit Jahren als Empfehlung bestehen, ohne dass Fortschritte erzielt wurden
  • Zombie-Code ohne Verantwortlichen und aktive Nutzer
  • Neue Funktionen, die einem veralteten System hinzugefügt wurden (investieren Sie stattdessen in den Ersatz)
  • Einstellung ohne Ermittlung der aktuellen Nutzung
  • Entfernung von Code, ohne zu überprüfen, ob tatsächlich keine aktiven Nutzer mehr vorhanden sind

Überprüfung

Nach Abschluss einer Ausmusterung:

  • Der Ersatz ist produktionserprobt und deckt alle kritischen Anwendungsfälle ab
  • Es liegt ein Migrationsleitfaden mit konkreten Schritten und Beispielen vor
  • Alle aktiven Verbraucher wurden migriert (über Metriken/Protokolle überprüft)
  • Alter Code, Tests, Dokumentation und Konfiguration wurden vollständig entfernt
  • In der Codebasis sind keine Verweise mehr auf das veraltete System vorhanden
  • Veraltungshinweise wurden entfernt (sie haben ihren Zweck erfüllt)
Auf GitHub ansehen
---
name: deprecation-and-migration
description: Guides the process of deprecating old systems, APIs, or features and migrating users to replacements, including decision frameworks, migration patterns, and removal strategies.
---

# Deprecation and Migration

## Overview

Code is a liability, not an asset. Every line of code has ongoing maintenance cost — bugs to fix, dependencies to update, security patches to apply, and new engineers to onboard. Deprecation is the discipline of removing code that no longer earns its keep, and migration is the process of moving users safely from the old to the new.

Most engineering organizations are good at building things. Few are good at removing them. This skill addresses that gap.

## When to Use

- Replacing an old system, API, or library with a new one
- Sunsetting a feature that's no longer needed
- Consolidating duplicate implementations
- Removing dead code that nobody owns but everybody depends on
- Planning the lifecycle of a new system (deprecation planning starts at design time)
- Deciding whether to maintain a legacy system or invest in migration

## Core Principles

### Code Is a Liability

Every line of code has ongoing cost: it needs tests, documentation, security patches, dependency updates, and mental overhead for anyone working nearby. The value of code is the functionality it provides, not the code itself. When the same functionality can be provided with less code, less complexity, or better abstractions — the old code should go.

### Hyrum's Law Makes Removal Hard

With enough users, every observable behavior becomes depended on — including bugs, timing quirks, and undocumented side effects. This is why deprecation requires active migration, not just announcement. Users can't "just switch" when they depend on behaviors the replacement doesn't replicate.

### Deprecation Planning Starts at Design Time

When building something new, ask: "How would we remove this in 3 years?" Systems designed with clean interfaces, feature flags, and minimal surface area are easier to deprecate than systems that leak implementation details everywhere.

## The Deprecation Decision

Before deprecating anything, answer these questions:

```
1. Does this system still provide unique value?
   → If yes, maintain it. If no, proceed.

2. How many users/consumers depend on it?
   → Quantify the migration scope.

3. Does a replacement exist?
   → If no, build the replacement first. Don't deprecate without an alternative.

4. What's the migration cost for each consumer?
   → If trivially automated, do it. If manual and high-effort, weigh against maintenance cost.

5. What's the ongoing maintenance cost of NOT deprecating?
   → Security risk, engineer time, opportunity cost of complexity.
```

## Compulsory vs Advisory Deprecation

| Type | When to Use | Mechanism |
|------|-------------|-----------|
| **Advisory** | Migration is optional, old system is stable | Warnings, documentation, nudges. Users migrate on their own timeline. |
| **Compulsory** | Old system has security issues, blocks progress, or maintenance cost is unsustainable | Hard deadline. Old system will be removed by date X. Provide migration tooling. |

**Default to advisory.** Use compulsory only when the maintenance cost or risk justifies forcing migration. Compulsory deprecation requires providing migration tooling, documentation, and support — you can't just announce a deadline.

## The Migration Process

### Step 1: Build the Replacement

Don't deprecate without a working alternative. The replacement must:

- Cover all critical use cases of the old system
- Have documentation and migration guides
- Be proven in production (not just "theoretically better")

### Step 2: Announce and Document

```markdown
## Deprecation Notice: OldService

**Status:** Deprecated as of 2025-03-01
**Replacement:** NewService (see migration guide below)
**Removal date:** Advisory — no hard deadline yet
**Reason:** OldService requires manual scaling and lacks observability.
            NewService handles both automatically.

### Migration Guide
1. Replace `import { client } from 'old-service'` with `import { client } from 'new-service'`
2. Update configuration (see examples below)
3. Run the migration verification script: `npx migrate-check`
```

### Step 3: Migrate Incrementally

Migrate consumers one at a time, not all at once. For each consumer:

```
1. Identify all touchpoints with the deprecated system
2. Update to use the replacement
3. Verify behavior matches (tests, integration checks)
4. Remove references to the old system
5. Confirm no regressions
```

**The Churn Rule:** If you own the infrastructure being deprecated, you are responsible for migrating your users — or providing backward-compatible updates that require no migration. Don't announce deprecation and leave users to figure it out.

### Step 4: Remove the Old System

Only after all consumers have migrated:

```
1. Verify zero active usage (metrics, logs, dependency analysis)
2. Remove the code
3. Remove associated tests, documentation, and configuration
4. Remove the deprecation notices
5. Celebrate — removing code is an achievement
```

## Migration Patterns

### Strangler Pattern

Run old and new systems in parallel. Route traffic incrementally from old to new. When the old system handles 0% of traffic, remove it.

```
Phase 1: New system handles 0%, old handles 100%
Phase 2: New system handles 10% (canary)
Phase 3: New system handles 50%
Phase 4: New system handles 100%, old system idle
Phase 5: Remove old system
```

### Adapter Pattern

Create an adapter that translates calls from the old interface to the new implementation. Consumers keep using the old interface while you migrate the backend.

```typescript
// Adapter: old interface, new implementation
class LegacyTaskService implements OldTaskAPI {
  constructor(private newService: NewTaskService) {}

  // Old method signature, delegates to new implementation
  getTask(id: number): OldTask {
    const task = this.newService.findById(String(id));
    return this.toOldFormat(task);
  }
}
```

### Feature Flag Migration

Use feature flags to switch consumers from old to new system one at a time:

```typescript
function getTaskService(userId: string): TaskService {
  if (featureFlags.isEnabled('new-task-service', { userId })) {
    return new NewTaskService();
  }
  return new LegacyTaskService();
}
```

## Zombie Code

Zombie code is code that nobody owns but everybody depends on. It's not actively maintained, has no clear owner, and accumulates security vulnerabilities and compatibility issues. Signs:

- No commits in 6+ months but active consumers exist
- No assigned maintainer or team
- Failing tests that nobody fixes
- Dependencies with known vulnerabilities that nobody updates
- Documentation that references systems that no longer exist

**Response:** Either assign an owner and maintain it properly, or deprecate it with a concrete migration plan. Zombie code cannot stay in limbo — it either gets investment or removal.

## Common Rationalizations

| Rationalization | Reality |
|---|---|
| "It still works, why remove it?" | Working code that nobody maintains accumulates security debt and complexity. Maintenance cost grows silently. |
| "Someone might need it later" | If it's needed later, it can be rebuilt. Keeping unused code "just in case" costs more than rebuilding. |
| "The migration is too expensive" | Compare migration cost to ongoing maintenance cost over 2-3 years. Migration is usually cheaper long-term. |
| "We'll deprecate it after we finish the new system" | Deprecation planning starts at design time. By the time the new system is done, you'll have new priorities. Plan now. |
| "Users will migrate on their own" | They won't. Provide tooling, documentation, and incentives — or do the migration yourself (the Churn Rule). |
| "We can maintain both systems indefinitely" | Two systems doing the same thing is double the maintenance, testing, documentation, and onboarding cost. |

## Red Flags

- Deprecated systems with no replacement available
- Deprecation announcements with no migration tooling or documentation
- "Soft" deprecation that's been advisory for years with no progress
- Zombie code with no owner and active consumers
- New features added to a deprecated system (invest in the replacement instead)
- Deprecation without measuring current usage
- Removing code without verifying zero active consumers

## Verification

After completing a deprecation:

- [ ] Replacement is production-proven and covers all critical use cases
- [ ] Migration guide exists with concrete steps and examples
- [ ] All active consumers have been migrated (verified by metrics/logs)
- [ ] Old code, tests, documentation, and configuration are fully removed
- [ ] No references to the deprecated system remain in the codebase
- [ ] Deprecation notices are removed (they served their purpose)

Alle Dateien

0 Dateien

deprecation-and-migration installieren

Laden Sie die Skill-Dateien herunter und entpacken Sie sie in Ihr Verzeichnis „.claude/skills/“.

ZIP herunterladen

Klonen Sie das Repository und kopieren Sie die Skill-Dateien in Ihr Projekt.

git clone https://github.com/addyosmani/agent-skills/tree/main/skills/deprecation-and-migration # Copy SKILL.md to your .claude/skills/ directory

Kopieren Kopieren
Schnelle Einrichtung: Kopiere den Skill-Ordner nach .claude/skills/ Claude erkennt den Skill automatisch und nutzt ihn.

Ähnliche Skills

algorithmic-art
Zeit aktualisiert 27. August 2026
receiving-code-review
Zeit aktualisiert 3. September 2026
tech-debt-tracker
Zeit aktualisiert 29. August 2026
senior-backend
Zeit aktualisiert 30. August 2026
OR