Communitygithub.com

Datenbank-Migrationen

Bewährte Methoden für Datenbankschema- und Datenmigrationen, Rollbacks und Ausfallzeit-freie Bereitstellungen für PostgreSQL, MySQL und gängige ORMs (Prisma, Drizzle, Kysely, Django, TypeORM, golang-migrate). Verwenden Sie diese, wenn Sie eine Schema- oder Datenmigration schreiben, ein Rollback planen oder eine Ausfallzeit-freie Bereitstellung anstreben.

Was ist Datenbank-Migrationen?

Dieser Skill bietet eine umfassende Anleitung für sichere, reversible Datenbankschema-Änderungen in Produktionssystemen und behandelt die wichtigsten Datenbanken (PostgreSQL, MySQL) und gängige ORMs (Prisma, Drizzle, Kysely, Django, TypeORM, golang-migrate). Er betont die Grundsätze, dass jede Änderung eine Migration ist, Migrationen in der Produktion vorwärtsgerichtet sind, Schema- und Datenmigrationen getrennt werden, Migrationen gegen produktionsnahe Daten getestet werden müssen und einmal bereitgestellte Migrationen unveränderlich sind. Der Skill enthält eine Sicherheitscheckliste, PostgreSQL-spezifische Muster (z. B. sicheres Hinzufügen von Spalten, nebenläufige Indexerstellung, Expand-Contract-Pattern für Umbenennungen) sowie detaillierte Workflows und Codebeispiele für jedes ORM. Zusätzlich wird eine Ausfallzeit-freie Migrationsstrategie mit einer dreiphasigen Expand-Migrate-Contract-Methode und typischen Anti-Patterns wie manuellem SQL in Produktion oder dem Bearbeiten bereits bereitgestellter Migrationen dokumentiert.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/database-migrations

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Datenbank-Migrationsmuster

Sichere, umkehrbare Datenbankschema-Änderungen für Produktionssysteme.

Wann aktivieren

  • Erstellen oder Ändern von Datenbanktabellen
  • Hinzufügen/Entfernen von Spalten oder Indizes
  • Ausführen von Datenmigrationen (Backfill, Transformation)
  • Planung von Schemaänderungen ohne Ausfallzeit
  • Einrichten von Migrationstools für ein neues Projekt

Kernprinzipien

  1. Jede Änderung ist eine Migration – niemals Produktionsdatenbanken manuell ändern
  2. Migrationen sind in der Produktion vorwärtsgerichtet – Rollbacks erfolgen durch neue Vorwärtsmigrationen
  3. Schema- und Datenmigrationen sind getrennt – niemals DDL und DML in einer Migration mischen
  4. Migrationen gegen produktionsnahe Daten testen – eine Migration, die mit 100 Zeilen funktioniert, kann bei 10 Millionen blockieren
  5. Migrationen sind nach der Bereitstellung unveränderlich – niemals eine Migration bearbeiten, die in der Produktion ausgeführt wurde

Sicherheitscheckliste für Migrationen

Vor dem Anwenden einer Migration:

  • Migration hat sowohl UP als auch DOWN (oder ist explizit als irreversibel gekennzeichnet)
  • Keine vollständigen Tabellensperren bei großen Tabellen (nebenläufige Operationen verwenden)
  • Neue Spalten haben Standardwerte oder sind nullable (niemals NOT NULL ohne Standardwert hinzufügen)
  • Indizes nebenläufig erstellen (nicht inline mit CREATE TABLE für bestehende Tabellen)
  • Daten-Backfill ist eine separate Migration von der Schemaänderung
  • Gegen eine Kopie der Produktionsdaten getestet
  • Rollback-Plan dokumentiert

PostgreSQL-Muster

Sichere Spalten hinzufügen

-- GUT: Nullable-Spalte, keine Sperre
ALTER TABLE users ADD COLUMN avatar_url TEXT;

-- GUT: Spalte mit Standardwert (Postgres 11+ ist sofort, kein Neuschreiben)
ALTER TABLE users ADD COLUMN is_active BOOLEAN NOT NULL DEFAULT true;

-- SCHLECHT: NOT NULL ohne Standardwert bei bestehender Tabelle (erfordert vollständiges Neuschreiben)
ALTER TABLE users ADD COLUMN role TEXT NOT NULL;
-- Dies sperrt die Tabelle und schreibt jede Zeile neu

Hinzufügen eines Index ohne Ausfallzeit

-- SCHLECHT: Blockiert Schreibvorgänge bei großen Tabellen
CREATE INDEX idx_users_email ON users (email);

-- GUT: Nicht blockierend, erlaubt nebenläufige Schreibvorgänge
CREATE INDEX CONCURRENTLY idx_users_email ON users (email);

-- Hinweis: CONCURRENTLY kann nicht innerhalb eines Transaktionsblocks ausgeführt werden
-- Die meisten Migrationstools benötigen dafür eine spezielle Behandlung

Umbenennen einer Spalte (Ausfallzeit-frei)

Niemals direkt in der Produktion umbenennen. Verwenden Sie das Expand-Contract-Muster:

-- Schritt 1: Neue Spalte hinzufügen (Migration 001)
ALTER TABLE users ADD COLUMN display_name TEXT;

-- Schritt 2: Daten backfillen (Migration 002, Datenmigration)
UPDATE users SET display_name = username WHERE display_name IS NULL;

-- Schritt 3: Anwendungscode aktualisieren, um beide Spalten zu lesen/schreiben
-- Anwendungsänderungen bereitstellen

-- Schritt 4: Schreiben in alte Spalte beenden, löschen (Migration 003)
ALTER TABLE users DROP COLUMN username;

Sicheres Entfernen einer Spalte

-- Schritt 1: Alle Anwendungsverweise auf die Spalte entfernen
-- Schritt 2: Anwendung ohne den Spaltenverweis bereitstellen
-- Schritt 3: Spalte in der nächsten Migration löschen
ALTER TABLE orders DROP COLUMN legacy_status;

-- Für Django: SeparateDatabaseAndState verwenden, um die Spalte aus dem Modell zu entfernen
-- ohne DROP COLUMN zu generieren (dann in der nächsten Migration löschen)

Große Datenmigrationen

-- SCHLECHT: Aktualisiert alle Zeilen in einer Transaktion (sperrt Tabelle)
UPDATE users SET normalized_email = LOWER(email);

-- GUT: Batch-Update mit Fortschritt
DO $$
DECLARE
  batch_size INT := 10000;
  rows_updated INT;
BEGIN
  LOOP
    UPDATE users
    SET normalized_email = LOWER(email)
    WHERE id IN (
      SELECT id FROM users
      WHERE normalized_email IS NULL
      LIMIT batch_size
      FOR UPDATE SKIP LOCKED
    );
    GET DIAGNOSTICS rows_updated = ROW_COUNT;
    RAISE NOTICE 'Updated % rows', rows_updated;
    EXIT WHEN rows_updated = 0;
    COMMIT;
  END LOOP;
END $$;

Prisma (TypeScript/Node.js)

Arbeitsablauf

# Migration aus Schemaänderungen erstellen
npx prisma migrate dev --name add_user_avatar

# Ausstehende Migrationen in der Produktion anwenden
npx prisma migrate deploy

# Datenbank zurücksetzen (nur Entwicklung)
npx prisma migrate reset

# Client nach Schemaänderungen generieren
npx prisma generate

Schema-Beispiel

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  avatarUrl String?  @map("avatar_url")
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")
  orders    Order[]

  @@map("users")
  @@index([email])
}

Benutzerdefinierte SQL-Migration

Für Operationen, die Prisma nicht ausdrücken kann (nebenläufige Indizes, Daten-Backfills):

# Leere Migration erstellen, dann SQL manuell bearbeiten
npx prisma migrate dev --create-only --name add_email_index
-- migrations/20240115_add_email_index/migration.sql
-- Prisma kann CONCURRENTLY nicht generieren, also schreiben wir es manuell
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users (email);

Drizzle (TypeScript/Node.js)

Arbeitsablauf

# Migration aus Schemaänderungen generieren
npx drizzle-kit generate

# Migrationen anwenden
npx drizzle-kit migrate

# Schema direkt pushen (nur Entwicklung, keine Migrationsdatei)
npx drizzle-kit push

Schema-Beispiel

import { pgTable, text, timestamp, uuid, boolean } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: uuid("id").primaryKey().defaultRandom(),
  email: text("email").notNull().unique(),
  name: text("name"),
  isActive: boolean("is_active").notNull().default(true),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow(),
});

Kysely (TypeScript/Node.js)

Arbeitsablauf (kysely-ctl)

# Konfigurationsdatei initialisieren (kysely.config.ts)
kysely init

# Neue Migrationsdatei erstellen
kysely migrate make add_user_avatar

# Alle ausstehenden Migrationen anwenden
kysely migrate latest

# Letzte Migration rückgängig machen
kysely migrate down

# Migrationsstatus anzeigen
kysely migrate list

Migrationsdatei

// migrations/2024_01_15_001_create_user_profile.ts
import { type Kysely, sql } from 'kysely'

// WICHTIG: Immer Kysely<any> verwenden, nicht die typisierte DB-Schnittstelle.
// Migrationen sind zum Zeitpunkt der Entstehung eingefroren und dürfen nicht
// von aktuellen Schematypen abhängen.
export async function up(db: Kysely<any>): Promise<void> {
  await db.schema
    .createTable('user_profile')
    .addColumn('id', 'serial', (col) => col.primaryKey())
    .addColumn('email', 'varchar(255)', (col) => col.notNull().unique())
    .addColumn('avatar_url', 'text')
    .addColumn('created_at', 'timestamp', (col) =>
      col.defaultTo(sql`now()`).notNull()
    )
    .execute()

  await db.schema
    .createIndex('idx_user_profile_avatar')
    .on('user_profile')
    .column('avatar_url')
    .execute()
}

export async function down(db: Kysely<any>): Promise<void> {
  await db.schema.dropTable('user_profile').execute()
}

Programmatischer Migrator

import { Migrator, FileMigrationProvider } from 'kysely'
import { promises as fs } from 'fs'
import * as path from 'path'
// Nur ESM — CJS kann __dirname direkt verwenden
import { fileURLToPath } from 'url'
const migrationFolder = path.join(
  path.dirname(fileURLToPath(import.meta.url)),
  './migrations',
)

// `db` ist Ihre Kysely<any>-Datenbankinstanz
const migrator = new Migrator({
  db,
  provider: new FileMigrationProvider({
    fs,
    path,
    migrationFolder,
  }),
  // WARNUNG: Nur in der Entwicklung aktivieren. Deaktiviert die Zeitstempel-Sortierung
  // – Validierung, die zu Schema-Drift zwischen Umgebungen führen kann.
  // allowUnorderedMigrations: true,
})

const { error, results } = await migrator.migrateToLatest()

results?.forEach((it) => {
  if (it.status === 'Success') {
    console.log(`migration "${it.migrationName}" executed successfully`)
  } else if (it.status === 'Error') {
    console.error(`failed to execute migration "${it.migrationName}"`)
  }
})

if (error) {
  console.error('migration failed', error)
  process.exit(1)
}

Django (Python)

Arbeitsablauf

# Migration aus Modelländerungen generieren
python manage.py makemigrations

# Migrationen anwenden
python manage.py migrate

# Migrationsstatus anzeigen
python manage.py showmigrations

# Leere Migration für benutzerdefiniertes SQL generieren
python manage.py makemigrations --empty app_name -n description

Datenmigration

from django.db import migrations

def backfill_display_names(apps, schema_editor):
    User = apps.get_model("accounts", "User")
    batch_size = 5000
    users = User.objects.filter(display_name="")
    while users.exists():
        batch = list(users[:batch_size])
        for user in batch:
            user.display_name = user.username
        User.objects.bulk_update(batch, ["display_name"], batch_size=batch_size)

def reverse_backfill(apps, schema_editor):
    pass  # Datenmigration, kein Reverse nötig

class Migration(migrations.Migration):
    dependencies = [("accounts", "0015_add_display_name")]

    operations = [
        migrations.RunPython(backfill_display_names, reverse_backfill),
    ]

SeparateDatabaseAndState

Eine Spalte aus dem Django-Modell entfernen, ohne sie sofort aus der Datenbank zu löschen:

class Migration(migrations.Migration):
    operations = [
        migrations.SeparateDatabaseAndState(
            state_operations=[
                migrations.RemoveField(model_name="user", name="legacy_field"),
            ],
            database_operations=[],  # Die DB noch nicht anfassen
        ),
    ]

golang-migrate (Go)

Arbeitsablauf

# Migrationspaar erstellen
migrate create -ext sql -dir migrations -seq add_user_avatar

# Alle ausstehenden Migrationen anwenden
migrate -path migrations -database "$DATABASE_URL" up

# Letzte Migration rückgängig machen
migrate -path migrations -database "$DATABASE_URL" down 1

# Version erzwingen (fehlerhaften Zustand beheben)
migrate -path migrations -database "$DATABASE_URL" force VERSION

Migrationsdateien

-- migrations/000003_add_user_avatar.up.sql
ALTER TABLE users ADD COLUMN avatar_url TEXT;
CREATE INDEX CONCURRENTLY idx_users_avatar ON users (avatar_url) WHERE avatar_url IS NOT NULL;

-- migrations/000003_add_user_avatar.down.sql
DROP INDEX IF EXISTS idx_users_avatar;
ALTER TABLE users DROP COLUMN IF EXISTS avatar_url;

Ausfallzeit-freie Migrationsstrategie

Für kritische Produktionsänderungen folgen Sie dem Expand-Contract-Muster:

Phase 1: EXPAND
  - Neue Spalte/Tabelle hinzufügen (nullable oder mit Standardwert)
  - Bereitstellen: App schreibt in BEIDE alt und neu
  - Vorhandene Daten backfillen

Phase 2: MIGRATE
  - Bereitstellen: App liest aus NEU, schreibt in BEIDE
  - Datenkonsistenz prüfen

Phase 3: CONTRACT
  - Bereitstellen: App verwendet nur NEU
  - Alte Spalte/Tabelle in separater Migration löschen

Zeitplanbeispiel

Tag 1: Migration fügt neue_Status-Spalte hinzu (nullable)
Tag 1: Bereitstellung App v2 – schreibt in status und neue_status
Tag 2: Backfill-Migration für vorhandene Zeilen ausführen
Tag 3: Bereitstellung App v3 – liest nur aus neue_status
Tag 7: Migration löscht alte status-Spalte

Anti-Patterns

Anti-PatternWarum es fehlschlägtBesserer Ansatz
Manuelles SQL in der ProduktionKeine Audit-Trail, nicht wiederholbarImmer Migrationsdateien verwenden
Bereitgestellte Migrationen bearbeitenVerursacht Drift zwischen UmgebungenStattdessen neue Migration erstellen
NOT NULL ohne StandardwertSperrt Tabelle, schreibt alle Zeilen neuNullable hinzufügen, backfillen, dann Einschränkung hinzufügen
Inline-Index bei großer TabelleBlockiert Schreibvorgänge während der ErstellungCREATE INDEX CONCURRENTLY
Schema + Daten in einer MigrationSchwer rückgängig zu machen, lange TransaktionenSeparate Migrationen
Spalte vor dem Entfernen des Codes löschenAnwendungsfehler durch fehlende SpalteZuerst Code entfernen, Spalte im nächsten Deployment löschen

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Verwandte Skills