Migracje baz danych i kodu z Claude Code
Migracja z Claude Code to ciąg faz wdrażanych osobno (expand, backfill, przełączenie odczytów i contract przy schemacie; codemod, poprawki agenta i weryfikacja przy aktualizacji frameworka), które Claude Code planuje, pisze i testuje na jednorazowej bazie albo gałęzi. Najważniejsze zastrzeżenie: każda faza trafia na produkcję dopiero wtedy, gdy przejdzie bramkę, a stosuje ją CI, nie agent.
Ta strona jest dla programistów, którzy prowadzą migrację w terminalu, i dla tech leadów, którzy ją zatwierdzają. Tabela users ma 12 milionów wierszy, a kolumna name ma się stać kolumnami first_name i last_name. Express 4 ma się stać Expressem 5 w 180 plikach z trasami. Operator płatności wyłącza API v1 z końcem kwartału. Claude Code napisze wszystkie pliki do tych trzech zadań w jedno popołudnie, a jeden z nich nadal może położyć produkcję.
Co zyskasz z migracji w Claude Code
Dział zatytułowany „Co zyskasz z migracji w Claude Code”- Konfigurację sesji, która trzyma agenta przy bazie roboczej i na gałęzi, którą możesz wyrzucić.
- Inwentaryzację w trybie planu, zbudowaną przez subagentów, która pokazuje zasięg zmian, zanim zmieni się jakikolwiek plik.
- Prompty do skopiowania: zmiana schematu metodą expand-contract, wznawialny backfill, aktualizacja frameworka, aktualizacja ORM i przejście na nową wersję API za flagą.
- Bramkę dla każdego rodzaju migracji, dzięki której sprawdzasz dowody, a nie każdą linię napisaną przez agenta.
- Sposoby, w jakie migracje psują się właśnie w Claude Code, łącznie z tym, czego
/rewindnie cofnie, wraz z wyjściem z każdej sytuacji.
Jaki rodzaj migracji prowadzisz?
Dział zatytułowany „Jaki rodzaj migracji prowadzisz?”Przebieg jest ten sam dla każdej migracji: inwentaryzacja, plan w fazach, wykonanie jednej fazy, dowód, dopiero potem wdrożenie. Zmienia się narzędzie, które wykonuje główną pracę, i dowód, który potwierdza fazę.
| Migracja | Główną pracę wykonuje | Dowód, że faza jest bezpieczna | Szczegóły |
|---|---|---|---|
| Zmiana schematu żywej tabeli | Claude Code pisze pliki faz, narzędzie do migracji je stosuje | Linter blokad, up-down-up na bazie roboczej, zapytanie o zgodność zwracające 0 | Wzorce migracji baz danych |
| Nowa główna wersja frameworka lub biblioteki | Najpierw codemod dostawcy, potem Claude Code dla tego, co pominął | Sprawdzenie typów, pełny zestaw testów, grep, który nie znajduje starego API | Operacje wsadowe |
| Nowa główna wersja ORM | Claude Code, według przewodnika aktualizacji dostawcy | SQL generowany przez ORM, porównany przed i po | Wzorce ORM |
| Nowa wersja zewnętrznego API | Claude Code, za flagą funkcji | Testy kontraktowe na nagranych odpowiedziach v2, potem porównanie w trybie cienia | Wdrażanie stopniowe |
Przepisanie całego systemu (zmiana języka, rozbicie monolitu) to program, nie migracja. Potrzebuje testów charakteryzujących i planu wycinków; zobacz modernizację starszego kodu z agentami.
Przygotuj sesję, zanim zaczniesz migrację
Dział zatytułowany „Przygotuj sesję, zanim zaczniesz migrację”Cztery kroki zapewniają, że migrację da się cofnąć. Wykonaj je w tej kolejności, bo każdy zakłada poprzedni.
-
Pracuj w worktree.
claude -w users-name-split(--worktreewclaude --help2.1.283) tworzy worktree gita i uruchamia w nim sesję, więc nieudana próba to katalog do usunięcia. -
Skieruj powłokę na bazę roboczą. Claude Code uruchamia polecenia z twoim środowiskiem. Od v2.1.283 na kanale
latesttryb auto jest domyślnym trybem uprawnień w interaktywnych sesjach terminalowych na obsługiwanych przez niego modelach, więc większość poleceń zatwierdza klasyfikator, a nie ty. JeśliDATABASE_URLwskazuje staging, jednomigrate deploytam dotrze. Uruchom jednorazowego Postgresa i wyeksportuj jego URL, zanim wpiszeszclaude. Praca z bazami danych w Claude Code zawiera polecenie kontenera, regułydenydla twojego narzędzia do migracji i serwer Postgres MCP Pro tylko do odczytu, przez który zajrzysz do stagingu:Okno terminala # Terminal, katalog główny repozytorium: Postgres MCP Pro tylko do odczytu dla staginguclaude mcp add -s project postgres -e 'DATABASE_URI=${STAGING_DATABASE_URL}' \-- uvx postgres-mcp --access-mode=restricted -
Zrób commit bazowy. Checkpointy i
/rewindprzywracają tylko zmiany zrobione narzędziami edycji plików Claude’a. Codemod,sedczymvuruchomione przez Bash nie są śledzone. Commit przed każdą fazą to twoje prawdziwe „cofnij”. -
Zapisz zasady migracji w
CLAUDE.md. Czyta je każda sesja, każdy subagent i każdy worker/batch. Gdzie umieścić plik, opisuje system pamięci.## Migrations- Never edit a migration file that has been applied anywhere. Write a new one.- One phase per migration file: expand, backfill, contract are separate files and separate deploys.- Every file starts with SET lock_timeout = '5s' and names the lock each statement takes.- The only database you may touch is $DATABASE_URL (local scratch). Never run migrate deploy.- Do not edit tests to make a migration pass. Report the failing test instead.
Żeby pierwsza zasada była mechanizmem, a nie prośbą, dodaj hook PreToolUse, który odrzuca Edit i Write w katalogach z zastosowanymi migracjami. Hooki Claude Code zawierają przetestowany skrypt protect-paths.sh do przerobienia.
Zmapuj zasięg zmian w trybie planu
Dział zatytułowany „Zmapuj zasięg zmian w trybie planu”Tryb planu pozwala Claude Code czytać i proponować bez edycji. Naciskaj Shift+Tab, aż wskaźnik pokaże tryb planu, albo uruchom claude --permission-mode plan. Poproś o inwentaryzację przez równoległych subagentów Explore: każdy przeszukuje jeden obszar i zwraca podsumowanie, więc główna sesja zachowuje kontekst na plan.
MIGRATION.md staje się kontraktem na resztę pracy. Sprawdź w nim trzy rzeczy: backfill następuje dopiero, gdy każda instancja zapisuje do starej i nowej kolumny, faza contract to osobne wydanie, a każda faza ma nazwany sposób wycofania. Zatwierdź plan i uruchamiaj każdą fazę jako osobne zadanie. Gdy kontekst sesji się zapełni, wpisz /clear i zacznij kolejną fazę od „Read MIGRATION.md and do phase 3”.
Zmień schemat żywej bazy metodą expand-contract
Dział zatytułowany „Zmień schemat żywej bazy metodą expand-contract”Expand-contract nigdy nie zmienia kolumny w miejscu. Dodajesz nowe kolumny, zapisujesz do starej i nowych, kopiujesz stare dane, przełączasz odczyty, a starą kolumnę usuwasz wydanie później. Stara i nowa wersja aplikacji działają na każdym etapie, więc wycofanie między fazami to ponowne wdrożenie, a nie odtwarzanie z kopii.
Zanim zrobisz cokolwiek dalej, udowodnij plik expand na bazie roboczej: zastosuj go, zastosuj plik down, porównaj wynik pg_dump --schema-only przed i po, i zastosuj go ponownie. Skrypt up-down-up znajdziesz w pracy z bazami danych w Claude Code. Pusty diff schematu dowodzi, że wycofanie działa, i nikt nie musi czytać SQL. Następnie sprawdź plik pod kątem groźnych blokad Squawkiem, linterem migracji PostgreSQL; przy błędzie kończy się niezerowym kodem, więc ta sama linia działa jako krok CI:
# Terminal albo CI: lintowanie każdego pliku migracji dodanego na tej gałęziFILES=$(git diff --name-only --diff-filter=A origin/main -- 'db/migrations/*.sql')[ -z "$FILES" ] || npx squawk-cli@2.66.0 $FILESBackfill dużej tabeli bez blokowania
Dział zatytułowany „Backfill dużej tabeli bez blokowania”Jeden UPDATE na 12 milionach wierszy trzyma blokady przez jedną długą transakcję i powoduje rozrost tabeli (bloat). Poproś o zadanie wsadowe, które da się przerwać i wznowić.
Kolejność jest tu wszystkim. Jeśli backfill ruszy, zanim każda instancja zacznie zapisywać do starej i nowej kolumny, stara instancja może zmienić name już po tym, jak backfill minął ten wiersz, i nowe kolumny zdezaktualizują się bez żadnego błędu. Blokady zakładane przez każde polecenie SQL, bramkę z linterem Squawk i wycofanie każdej fazy opisują wzorce migracji baz danych.
Zaktualizuj framework: najpierw codemod, potem agent
Dział zatytułowany „Zaktualizuj framework: najpierw codemod, potem agent”Codemod dostawcy jest deterministyczny i tani, więc uruchom go, zanim wydasz tokeny. Potem Claude Code zajmuje się tym, czego codemod nie obejmuje, i czyta przewodnik migracji dostawcy zamiast polegać na własnej pamięci o API.
Przy przejściu z Expressa 4 na 5 pakiet zespołu Expressa @expressjs/codemod (0.0.5) ma cztery transformacje: magiczne przekierowanie "back", nazwy metod w liczbie mnogiej, przestarzałe sygnatury z v4 oraz req.param(). Pakiet jest oznaczony w npm jako przestarzały (sprawdzone 2026-09-26) i odsyła do codemodów Expressa w rejestrze codemod.com (zakres expressjs). Ta strona zostaje przy pakiecie z npm, bo nadal działa i obejmuje te cztery transformacje; rejestr traktuj jako miejsce na nowsze przepisy. Jego polecenie upgrade nie ma trybu podglądu, więc uruchom go na czystym drzewie i traktuj git diff jako podgląd; git restore . cofa zmiany:
# Terminal, w worktree, po commicie bazowymnpx @expressjs/codemod upgrade srcgit add -A && git commit -m "Express 5: apply official codemod"Typowa luka to ścieżki tras: Express 5 parsuje je przez path-to-regexp 8 (za pośrednictwem router 2), więc składnia symboli wieloznacznych i opcjonalnych segmentów wymaga zmian, których codemod nie robi.
Gdy zmiana obejmuje setki plików w wielu katalogach, /batch dzieli ją na 5 do 30 jednostek, każdą we własnym worktree i z własnym pull requestem. Przekaż mu przepis weryfikacji z kroków 3 i 4 powyżej; prompt i kolejność scalania opisują operacje wsadowe.
Zaktualizuj ORM, porównując generowany SQL
Dział zatytułowany „Zaktualizuj ORM, porównując generowany SQL”Aktualizacja ORM może przejść wszystkie testy i mimo to zmienić zachowanie: inna domyślna kolejność, inna obsługa NULL w filtrze albo nowa postać zapytania, która omija indeks. Sprawdzanie typów tego nie zobaczy. SQL tak.
Recenzent czyta diff SQL. Kilka zmienionych zapytań, każde z wyjaśnieniem, to recenzja całej aktualizacji; zmiany w miejscach wywołań pokrywają sprawdzanie typów i testy.
Przejdź na nową wersję zewnętrznego API za flagą
Dział zatytułowany „Przejdź na nową wersję zewnętrznego API za flagą”Zmiana wersji API dotyczy kodu, którego drugiej strony nie kontrolujesz, więc najpierw wdróż ją jako ukrytą (dark launch). Nagraj prawdziwe odpowiedzi v2 w sandboksie dostawcy, zbuduj na nich testy kontraktowe i przełączaj ruch flagą.
Włącz tryb cienia na produkcji dla wywołań tylko do odczytu, poczekaj, aż dziennik różnic spadnie do zera, a potem przenoś ruch zapisu flagą, krok po kroku. Rozłożenie wdrożenia na etapy i automatyczne wycofanie opisuje wdrażanie stopniowe.
Skąd wiesz, że migracja jest poprawna, bez czytania każdej linii?
Dział zatytułowany „Skąd wiesz, że migracja jest poprawna, bez czytania każdej linii?”Każda faza zostawia dowody. Recenzent czyta dowody, a uwagę linia po linii poświęca tylko tam, gdzie żadna bramka nie oceni wyniku.
| Wynik fazy | Bramka, która go dowodzi | Kto zatwierdza |
|---|---|---|
Plan w MIGRATION.md | Każda faza ma nazwane wdrożenie, bramkę i wycofanie; backfill następuje po zapisie do starej i nowej kolumny | Tech lead, przed zatwierdzeniem trybu planu |
| Plik expand lub contract | Squawk przechodzi; up, down, up na bazie roboczej z pustym diffem schematu; CI to powtarza | Właściciel schematu, przez CODEOWNERS na katalogu migracji |
| Backfill | Zapytanie o zgodność zwraca 0 na danych z przypadkami brzegowymi, potem na produkcji przez rolę tylko do odczytu | Właściciel migracji, z oboma wynikami w pull requeście |
| Aktualizacja frameworka | Sprawdzenie typów, pełny zestaw testów i grep za usuniętym API, który nic nie zwraca | CI |
| Aktualizacja ORM | Diff SQL przed i po, każde zmienione zapytanie wyjaśnione | Recenzent pull requesta |
| Nowa wersja API | Testy kontraktowe na nagranych odpowiedziach; dziennik różnic trybu cienia na zerze | Właściciel usługi, zanim flaga się przesunie |
Dwie rzeczy zawsze czyta człowiek: fazę contract, która usuwa dane, i każdy krok oznaczony w planie jako nieodwracalny. Migracje należą do nielicznych klas zmian, przy których takie czytanie nadal się opłaca, co wyjaśnia czytanie dowodów zamiast kodu. Wszystko inne trafia do pakietu dowodów pull requesta.
Żeby powtórzyć kontrolę w CI bez człowieka, uruchom przegląd nowych plików migracji tylko do odczytu przez claude -p. Ten tryb startuje jako Manual i nie może odpowiadać na pytania o uprawnienia, więc --allowedTools to cała jego powierzchnia narzędzi, a --json-schema zamienia wynik w plik, który sprawdzi kolejny krok:
# Zadanie CI na zaufanej gałęzi (push do main albo pull request z tego samego repozytorium)FILES=$(git diff --name-only --diff-filter=A origin/main -- 'db/migrations/*.sql')claude -p "Review these new migration files: $FILES. For every statement, name the lock it takes, whether the paired down migration reverses it, and whether it can lose data." \ --bare --setting-sources "" --strict-mcp-config \ --allowedTools "Read Grep Glob" \ --output-format json \ --json-schema "$(cat .github/migration-review.schema.json)" \ > migration-review.jsonjq -e '.subtype == "success" and .is_error == false' migration-review.json > /dev/nullPlik schematu opisuje tablicę obiektów {file, statement, lock, reversible, loses_data}; kolejny krok kończy zadanie błędem, gdy któryś wpis ma loses_data: true bez etykiety zatwierdzenia przez człowieka. Linia jq -e kończy zadanie błędem, gdy przebieg się nie dokończył, więc przerwany albo ucięty limitem przegląd nigdy nie przejdzie jako pusty. --bare --setting-sources "" --strict-mcp-config nie pozwala hookom, ustawieniom ani .mcp.json z gałęzi załadować się obok ANTHROPIC_API_KEY; --bare uwierzytelnia się wyłącznie tym kluczem. W pull requeście workflow, plik schematu i kolejny krok pochodzą z samego pull requesta, więc obejmij .github/ wpisem w CODEOWNERS z wymaganym przeglądem, inaczej pull request może osłabić kontrolę w tym samym diffie. Uruchamiaj to tylko na zaufanych gałęziach i nigdy na kodzie z forka w zdarzeniu pull_request_target: hooki i serwery MCP z katalogu .claude/ autora działałyby z sekretami zadania. Bezpieczny workflow na ten przypadek opisuje CI/CD z Claude Code.
Co się psuje, gdy migrujesz z Claude Code
Dział zatytułowany „Co się psuje, gdy migrujesz z Claude Code”/rewind nie cofnął codemodu. Checkpointy śledzą tylko zmiany zrobione narzędziami edycji plików Claude’a, a nie pliki zmienione poleceniem Bash. Wyjście: git, czyli git restore . do commita bazowego albo git reset --hard w worktree. Zapobieganie: commit przed każdą fazą.
Backfill wyczerpuje pamięć albo spowalnia bazę główną. Skrypt ładował wiersze do pamięci albo działał bez przerw. Zatrzymaj go; dzięki filtrowi first_name IS NULL nic nie przepada. Poproś Claude Code o mniejsze partie, stronicowanie keyset i logowanie ostatniego id, a potem wznów przez --start-after.
Trigger synchronizujący wywołuje się rekurencyjnie albo podwaja czas zapisu. Trigger BEFORE na poziomie wiersza, który tylko przypisuje kolumny NEW, nie wywołuje się rekurencyjnie. Jeśli agent napisał trigger AFTER, który aktualizuje własną tabelę, odpala się on ponownie: przepisz go na trigger BEFORE i zostaw zabezpieczenie pg_trigger_depth(). W obu przypadkach zmierz czas wstawiania na bazie roboczej przed plikiem expand i po nim. Jeśli koszt jest za wysoki, usuń trigger i polegaj na zapisie do obu kolumn w aplikacji, co oznacza, że backfill musi poczekać, aż nie będzie żadnej starej instancji.
Zapytanie o zgodność nie zwraca zera po backfillu. Instancja w starej wersji zapisała tylko name albo funkcja rozbijająca daje niespójne wyniki na przypadkach brzegowych. Upewnij się, że każda instancja działa w wersji z zapisem do obu kolumn, uruchom partię naprawczą z filtrem na niezgodność zamiast IS NULL i przejrzyj tabelę do weryfikacji. Nie wdrażaj fazy contract, dopóki wynik nie wynosi 0.
Migracja przechodzi na danych testowych i pada na produkcji. Produkcja ma wartości, których nie ma w danych startowych: NULL tam, gdzie schemat na to pozwala, puste napisy, bardzo długie napisy, nietypowy Unicode. Poproś Claude Code o zapytanie wstępne, które policzy każdy z tych przypadków w zmienianych kolumnach, uruchom je przez rolę tylko do odczytu i dodaj te przypadki do danych startowych.
Claude Code zmienił zastosowaną migrację albo test, żeby dojść do zielonego. Sesja miała prawo zapisu do obu. Przywróć plik z gita, powtórz zasadę i zamień ją w mechanizm: hook protect-paths.sh i reguła deny dla Edit na plikach testów. Zobacz ochronę wyroczni testowej.
Długa aktualizacja gubi wątek w połowie. Kontekst zapełnił się wynikami testów, a wczesne decyzje zostały streszczone. Trzymaj stan w MIGRATION.md, poproś Claude Code o odhaczanie w nim każdej fazy i zaczynaj każdą fazę w nowej sesji.
Co dalej z migracjami
Dział zatytułowany „Co dalej z migracjami”Ta sama praca w innych narzędziach: modernizacja kodu w Codex, praca z bazami danych w Codex i migracje w Cursorze.