22 paź 2025·8 min czytania

Ewolucja schematu odporna na regenerację dla przewidywalnych migracji

Ewolucja schematu odporna na regenerację utrzymuje dane produkcyjne poprawne, gdy backend jest regenerowany. Naucz się praktycznego sposobu planowania zmian schematu i migracji.

Ewolucja schematu odporna na regenerację dla przewidywalnych migracji

Dlaczego zmiany schematu wydają się ryzykowne przy regeneracji backendu

Gdy backend jest regenerowany z modelu wizualnego, zmiana w bazie danych może przypominać pociągnięcie nitki w swetrze. Zmieniasz pole w Data Designer, klikasz regeneruj i nagle nie tylko modyfikujesz tabelę. Zmieniasz też wygenerowane API, reguły walidacji i zapytania, których aplikacja używa do odczytu i zapisu danych.

To, co zwykle idzie nie tak, to nie to, że nowy kod się nie kompiluje. Wiele platform bez kodu (w tym AppMaster, który generuje prawdziwy kod w Go dla backendów) chętnie wygeneruje czysty projekt za każdym razem. Prawdziwe ryzyko polega na tym, że dane produkcyjne już istnieją i nie przekształcają się automatycznie, by pasować do Twoich nowych założeń.

Dwa pierwsze problemy, które ludzie zauważają, są proste:

  • Uszkodzone odczyty: aplikacja nie może wczytać rekordów, bo kolumna się przesunęła, typ się zmienił albo zapytanie oczekuje czegoś, czego tam nie ma.
  • Uszkodzone zapisy: nowe lub zaktualizowane rekordy odrzucane są przez zmienione ograniczenia, pola wymagane lub formaty, a klienci ciągle wysyłają stary kształt.

Oba błędy bolą, bo mogą ujawnić się dopiero gdy dotkną ich prawdziwi użytkownicy. Baza na stagingu może być pusta lub świeżo zasiana, więc wszystko wygląda dobrze. Produkcja ma przypadki brzegowe: null-e tam, gdzie zakładałeś wartości, stare ciągi enuma albo wiersze utworzone przed wprowadzeniem nowej reguły.

Dlatego ważna jest ewolucja schematu odporna na regenerację. Celem jest, żeby każda zmiana była bezpieczna nawet gdy kod backendu zostanie w pełni zregenerowany — stare rekordy pozostają ważne, a nowe można tworzyć.

„Przewidywalne migracje” oznaczają po prostu, że przed wdrożeniem potrafisz odpowiedzieć na cztery pytania: co zmieni się w bazie, co stanie się ze starymi wierszami, która wersja aplikacji będzie działać podczas rollout, i jak się wycofasz, jeśli pojawi się coś nieoczekiwanego.

Prosty model: schemat, migracje i zregenerowany kod

Gdy platforma może regenerować backend, warto rozdzielić w głowie trzy rzeczy: schemat bazy danych, kroki migracji, które go zmieniają, oraz dane żywe już na produkcji. Mieszanie tych pojęć powoduje, że zmiany wydają się nieprzewidywalne.

Myśl o regeneracji jako o „przebudowie kodu aplikacji z najnowszego modelu”. W narzędziu takim jak AppMaster ta przebudowa może odbywać się wielokrotnie w normalnej pracy: poprawiasz pole, dostosowujesz logikę biznesową, dodajesz endpoint, regenerujesz, testujesz, powtarzasz. Regeneracja jest częsta. Twoja baza produkcyjna nie powinna być.

Oto prosty model.

  • Schemat: struktura tabel, kolumn, indeksów i ograniczeń w bazie. To, czego baza oczekuje.
  • Migracje: uporządkowane, powtarzalne kroki przenoszące schemat z jednej wersji do drugiej (czasem też przenoszą dane). To uruchamiasz na każdym środowisku.
  • Dane w czasie działania (runtime data): prawdziwe rekordy tworzone przez użytkowników i procesy. Muszą pozostać poprawne przed, w trakcie i po zmianie.

Zregenerowany kod traktuj jako „obecną aplikację, która rozmawia z aktualnym schematem”. Migracje są mostem, który utrzymuje zgodność schematu i danych w czasie, gdy kod się zmienia.

Dlaczego regeneracja zmienia zasady gry

Jeśli regenerujesz często, naturalnie wprowadzisz wiele małych zmian schematu. To normalne. Ryzyko pojawia się, gdy te zmiany sugerują niezgodną wstecz zmianę bazy albo gdy migracja nie jest deterministyczna.

Praktyczny sposób na radzenie sobie z tym to planowanie ewolucji schematu odpornej na regenerację jako serii małych, odwracalnych kroków. Zamiast jednego dużego przełączenia, wykonujesz kontrolowane ruchy, które utrzymują stare i nowe ścieżki kodu działające razem przez krótki czas.

Na przykład, jeśli chcesz zmienić nazwę kolumny używanej przez żywe API, nie rób tego od razu. Najpierw dodaj nową kolumnę, zapisuj do obu, backfilluj istniejące wiersze, potem przełącz odczyty na nową kolumnę. Dopiero potem usuń starą kolumnę. Każdy krok jest łatwy do przetestowania, a jeśli coś pójdzie nie tak, możesz wstrzymać proces bez uszkadzania danych.

Ten sposób myślenia sprawia, że migracje są przewidywalne, nawet gdy regeneracja kodu odbywa się codziennie.

Rodzaje zmian schematu i które psują produkcję

Gdy backend jest regenerowany z najnowszego schematu, kod zwykle zakłada, że baza już teraz odpowiada temu schematowi. Dlatego ewolucja schematu odporna na regenerację to mniej pytanie „Czy możemy zmienić bazę?” a bardziej „Czy stare dane i stare żądania przetrwają rollout?”.

Niektóre zmiany są naturalnie bezpieczne, bo nie unieważniają istniejących wierszy ani zapytań. Inne zmieniają znaczenie danych lub usuwają coś, czego aplikacja nadal oczekuje — i to tam pojawiają się incydenty produkcyjne.

Niskie ryzyko, zwykle bezpieczne (additive)

Zmiany addytywne są najłatwiejsze do wdrożenia, bo mogą współistnieć ze starymi danymi.

  • Nowa tabela, od której nic jeszcze nie zależy.
  • Nowa kolumna nullable bez wymaganego defaultu.
  • Nowe pole API, które jest opcjonalne end-to-end.

Przykład: dodanie nullable kolumny middle_name do tabeli users jest zwykle bezpieczne. Istniejące wiersze pozostają poprawne, zregenerowany kod może ją odczytać gdy jest obecna, a starsze wiersze po prostu mają NULL.

Średnie ryzyko (zmiany znaczenia)

Te zmiany często „technicznie działają”, ale psują zachowanie. Wymagają koordynacji, bo regeneracja aktualizuje walidacje, wygenerowane modele i założenia logiki biznesowej.

Renamingi to klasyczna pułapka: zmiana phone na mobile_phone może spowodować, że zregenerowany kod przestanie czytać phone, podczas gdy produkcja dalej ma tam dane. Podobnie, zmiana jednostek (przechowywać cenę w dolarach zamiast w centach) może cicho zniszczyć obliczenia, jeśli najpierw zaktualizujesz kod, albo najpierw dane.

Enuma to kolejna ostrożna strefa. Zawężenie enuma (usunięcie wartości) może uczynić istniejące wiersze niepoprawnymi. Rozszerzenie enuma (dodanie wartości) jest zwykle bezpieczne, ale tylko jeśli wszystkie ścieżki kodu potrafią obsłużyć nową wartość.

Praktyczne podejście: traktuj zmiany znaczenia jako „dodaj nowe, backfilluj, przełącz, potem usuń”.

Wysokie ryzyko (destrukcyjne)

Zmiany destrukcyjne najczęściej natychmiast psują produkcję, szczególnie gdy platforma regeneruje kod, który przestaje oczekiwać starego kształtu.

Usunięcie kolumny, usunięcie tabeli lub zmiana kolumny z nullable na not-null może spowodować błędy zapisu w momencie, gdy jakiekolwiek żądanie spróbuje wstawić wiersz bez tej wartości. Nawet jeśli myślisz „wszystkie wiersze już ją mają”, kolejny przypadek brzegowy lub job w tle to obnaży.

Jeśli musisz zrobić not-null, rób to etapami: dodaj kolumnę jako nullable, backfilluj, zaktualizuj logikę aplikacji, aby zawsze ją ustawiać, a dopiero potem wymuś not-null.

Zmiany wydajności i bezpieczeństwa (mogą blokować zapisy)

Indeksy i ograniczenia to nie zmiana kształtu danych, ale nadal mogą powodować przestoje. Tworzenie indeksu na dużej tabeli lub dodanie unikalnego ograniczenia może blokować zapisy na tyle długo, by powodować timeouty. W PostgreSQL pewne operacje są bezpieczniejsze przy metodach online, ale kluczowa jest synchronizacja: wykonuj ciężkie operacje podczas niskiego ruchu i zmierz ich czas na kopii stagingowej.

Gdy zmiana wymaga dodatkowej ostrożności w produkcji, zaplanuj:

  • Dwustopniowy rollout (najpierw schemat, potem kod, albo odwrotnie) który pozostaje kompatybilny.
  • Backfille uruchamiane partiami.
  • Jasną ścieżkę rollback (co się stanie, gdy zregenerowany backend pójdzie live zbyt wcześnie).
  • Zapytania weryfikujące, które potwierdzą, że dane spełniają nowe reguły.
  • Zlecenie „usuń stare pole później”, żeby sprzątanie nie odbywało się w tym samym deployu.

Jeśli używasz platformy takiej jak AppMaster, która regeneruje kod backendu z Data Designer, najbezpieczniejsze podejście to: wprowadzaj zmiany, z którymi stare dane mogą żyć dzisiaj, a potem dopiero zaostrzaj reguły, gdy system już się do nich dostosował.

Zasady dla zmian odpornych na regenerację

Zregenerowane backendy są świetne, dopóki zmiana schematu nie trafi na produkcję i stare wiersze nie będą pasowały do nowego kształtu. Celem ewolucji schematu odpornej na regenerację jest prosty: utrzymać działanie aplikacji, podczas gdy baza danych i zregenerowany kod doganiają się w małych, przewidywalnych krokach.

Domyślnie: "rozszerz, migruj, skurcz się"

Traktuj każdą znaczącą zmianę jako trzy ruchy. Najpierw rozszerz schemat, żeby zarówno stary, jak i nowy kod mogły działać. Potem migruj dane. Dopiero potem skurcz się usuwając stare kolumny, domyślne wartości lub ograniczenia.

Praktyczna zasada: nigdy nie łącz "nowa struktura" i "destrukcyjne sprzątanie" w tym samym deployu.

Wspieraj stare i nowe kształty przez jakiś czas

Zakładaj, że będzie okres, gdy:

  • niektóre rekordy mają nowe pola, niektóre nie
  • niektóre instancje aplikacji uruchamiają stary kod, niektóre zregenerowany
  • joby w tle, importy czy aplikacje mobilne mogą pozostawać w tyle

Projektuj bazę tak, żeby oba kształty były ważne podczas tego overlapu. To ma znaczenie zwłaszcza gdy platforma regeneruje backend z najnowszego modelu (na przykład w AppMaster, gdy aktualizujesz Data Designer i regenerujesz backend w Go).

Uczyń odczyty kompatybilnymi przed zapisami

Zacznij od tego, by nowy kod bezpiecznie czytał stare dane. Dopiero potem przełącz ścieżki zapisu na produkcję nowego kształtu.

Na przykład, jeśli rozdzielasz jedno pole status na status + status_reason, wypuść kod, który radzi sobie z brakiem status_reason najpierw. Potem zacznij zapisywać status_reason przy nowych aktualizacjach.

Zdecyduj, co zrobić z częściowymi i nieznanymi danymi

Gdy dodajesz enuma, kolumnę non-null lub zaostrzające ograniczenia, ustal wcześniej, co robić gdy wartości brak lub są nieoczekiwane:

  • pozwól na null-e tymczasowo, potem backfilluj
  • ustaw bezpieczny domyślny, który nie zmienia znaczenia
  • zachowaj wartość "unknown", aby uniknąć błędów odczytu

To zapobiega cichej korupcji (złe domyślne) i twardym błędom (nowe ograniczenia odrzucające stare wiersze).

Miej historię rollback dla każdego kroku

Rollback jest najprostszy w fazie rozszerzania. Jeśli musisz się cofnąć, stary kod powinien nadal działać na rozszerzonym schemacie. Zapisz, co byś cofnął (tylko kod, czy kod plus migracja) i unikaj destrukcyjnych zmian dopóki nie będziesz pewien, że nie trzeba wycofać.

Krok po kroku: zaplanuj zmianę, która przetrwa regenerację

Wybierz ścieżkę wdrożenia
Wdrażaj zregenerowaną aplikację w chmurze lub eksportuj źródła, gdy potrzebujesz pełnej kontroli.
Wdróż aplikację

Zregenerowane backendy nie wybaczają: jeśli schemat i wygenerowany kod się nie zgadzają, produkcja zwykle to znajdzie pierwsza. Najbezpieczniejsze podejście to traktować każdą zmianę jako mały, odwracalny rollout, nawet jeśli budujesz w narzędziach no-code.

Zacznij od zapisania intencji prostym językiem i jak wyglądają teraz dane. Wybierz 3–5 prawdziwych wierszy z produkcji (lub ostatniego zrzutu) i zanotuj kłopotliwe miejsca: puste wartości, stare formaty, zaskakujące domyślne. To zapobiega projektowaniu idealnego nowego pola, którego realne dane nie spełnią.

Oto praktyczna sekwencja, która działa dobrze, gdy platforma regeneruje kod backendu (na przykład gdy AppMaster regeneruje usługi backend w Go z modelu Data Designer):

  1. Najpierw rozszerzaj, nie zastępuj. Dodaj nowe kolumny lub tabele w sposób addytywny. Na początku oznacz nowe pola jako nullable albo daj bezpieczne domyślne. Jeśli wprowadzasz nową relację, pozwól na pusty foreign key do czasu jej wypełnienia.

  2. Wdróż rozszerzony schemat bez usuwania czegokolwiek. Wprowadź zmianę bazy, podczas gdy stary kod nadal działa. Cel: stary kod może dalej zapisywać stare kolumny, a baza je akceptuje.

  3. Backfill jako kontrolowany job. Wypełniaj nowe pola partiami, monitoruj i uruchamiaj ponownie jeśli trzeba. Uczyń job idempotentnym (uruchomienie go dwa razy nie powinno zepsuć danych). Rób to stopniowo dla dużych tabel i loguj liczbę zaktualizowanych wierszy.

  4. Najpierw przełącz odczyty, z fallbackem. Zaktualizuj zregenerowaną logikę, żeby preferowała nowe pola, ale fallbackowała do starych, gdy nowe są puste. Dopiero gdy odczyty są stabilne, przełącz zapisy na nowe pola.

  5. Sprzątaj na końcu. Gdy masz pewność (i plan rollback), usuń stare pola i zaostrz ograniczenia: ustaw NOT NULL, dodaj UNIQUE, wymuś foreign key.

Konkretna ilustracja: chcesz zastąpić wolnotekstowe status polem status_id wskazującym na tabelę statuses. Dodaj status_id jako nullable, backfilluj z istniejących tekstów, zaktualizuj aplikację, aby czytała status_id ale fallbackowała do status gdy jest null, potem usuń status i ustaw status_id jako wymagane. To utrzymuje bezpieczeństwo regeneracji, bo baza jest kompatybilna na każdym etapie.

Wzorce praktyczne, które możesz ponownie używać

Buduj z bezpieczniejszymi zmianami schematu
Modeluj bazę danych wizualnie i regeneruj backend w Go bez ręcznego przepisywania kodu.
Wypróbuj AppMaster

Gdy backend się regeneruje, drobne poprawki schematu mogą rozlać się na API, walidacje i formularze UI. Celem jest wprowadzać zmiany tak, by stare dane były ważne, gdy nowy kod się wdraża.

Wzorzec 1: Bezpieczny rename

Bezpośrednia zmiana nazwy jest ryzykowna, bo stare rekordy i stary kod często dalej jej oczekują. Bezpieczniej potraktować rename jako krótki okres migracji.

  • Dodaj nową kolumnę (np. customer_phone) i zostaw starą (phone).
  • Zaktualizuj logikę, by dual-write: przy zapisie zapisuj do obu pól.
  • Backfilluj istniejące wiersze, by customer_phone był wypełniony.
  • Przełącz odczyty na nową kolumnę gdy pokrycie jest wysokie.
  • Usuń starą kolumnę w kolejnej wersji.

To dobrze działa w narzędziach takich jak AppMaster, gdzie regeneracja przebuduje modele i endpointy z aktualnego schematu. Dual-write utrzymuje szczęście obu generacji kodu podczas przejścia.

Wzorzec 2: Rozbicie jednego pola na dwa

Rozbicie full_name na first_name i last_name jest podobne, ale backfill trudniejszy. Zachowaj full_name dopóki nie będziesz pewien, że rozbicie jest kompletne.

Praktyczna zasada: nie usuwaj oryginalnego pola dopóki każdy rekord nie jest albo backfillowany, albo ma jasny fallback. Jeśli parsowanie zawiedzie, przechowaj cały ciąg w last_name i oznacz rekord do ręcznego sprawdzenia.

Wzorzec 3: Uczynienie pola wymaganym

Zamiana nullable na required to klasyczny breaker produkcyjny. Bezpieczna kolejność: najpierw backfill, potem egzekwuj.

Backfill może być mechaniczny (ustaw domyślny) lub wymagający interakcji biznesowej (poproś użytkowników o uzupełnienie). Dopiero gdy dane będą kompletne, dodaj NOT NULL i zaktualizuj walidacje. Jeśli regenerowany backend automatycznie doda ostrzejszą walidację, ta sekwencja zapobiega niespodziewanym błędom.

Wzorzec 4: Bezpieczna zmiana enuma

Zmiany enuma psują, gdy stary kod wysyła stare wartości. W okresie przejściowym akceptuj oba. Jeśli zamieniasz "pending" na "queued", trzymaj obie wartości ważne i mapuj je w logice. Gdy potwierdzisz, że nikt nie wysyła starej wartości, usuń ją.

Jeśli zmiana musi pójść jednym releasem, zmniejsz ryzyko przez zawężenie blast radius:

  • Dodaj nowe pola, ale zostaw stare nawet jeśli nieużywane.
  • Użyj domyślnych wartości, żeby insert-y nadal działały.
  • Uczyń kod tolerancyjnym: czytaj z nowego, fallbackuj do starego.
  • Dodaj tymczasową warstwę mapującą (stara wartość przychodzi, nowa jest zapisywana).

Te wzorce utrzymują migracje przewidywalne, nawet gdy regenerowany kod szybko zmienia zachowanie.

Częste błędy powodujące niespodzianki

Największe niespodzianki pojawiają się, gdy ludzie traktują regenerację kodu jak magiczny przycisk resetu. Regenerowane backendy utrzymują kod czystym, ale Twoja produkcyjna baza nadal zawiera wczorajsze dane w wczorajszym kształcie. Ewolucja schematu odporna na regenerację oznacza planowanie obu stron: nowego kodu i starych rekordów w tabelach.

Jedna pułapka to założenie, że platforma "zajmie się migracjami". Na przykład w AppMaster możesz zregenerować backend w Go z Data Designer, ale platforma nie zgadnie, jak chcesz przekształcić realne dane klientów. Jeśli dodasz nowe pole wymagane, wciąż potrzebujesz planu, jak istniejącym wierszom nadać wartość.

Inna niespodzianka to usuwanie lub zmiana nazw pól zbyt wcześnie. Pole może wydawać się nieużywane w głównym UI, ale nadal być czytane przez raport, eksport, webhook lub ekran admina, który ktoś rzadko otwiera. Zmiana wygląda bezpiecznie w testach, a potem psuje się w produkcji, bo jedna zapomniana ścieżka kodu dalej oczekuje starej nazwy kolumny.

Oto pięć błędów, które zwykle powodują nocne rollbacki:

  • Zmiana schematu i regeneracja kodu bez wykonania lub weryfikacji migracji danych, które czynią stare wiersze poprawnymi.
  • Zmienianie nazwy lub usuwanie kolumny zanim każdy reader i writer zostaną zaktualizowani i wdrożeni.
  • Backfill dużej tabeli bez sprawdzenia, ile czasu to zajmie i czy zablokuje inne zapisy.
  • Dodanie nowego ograniczenia (NOT NULL, UNIQUE, foreign key) najpierw, a potem odkrycie danych legacy, które je łamią.
  • Zapomnienie o jobach w tle, eksportach i raportach, które nadal czytają stare pola.

Prosty scenariusz: zmieniasz phone na mobile_number, dodajesz NOT NULL i regenerujesz. Ekrany aplikacji mogą działać, ale starszy eksport CSV wciąż wybiera phone, a tysiące istniejących rekordów mają null w mobile_number. Naprawa to zwykle etapowa zmiana: dodaj nową kolumnę, dual-write przez jakiś czas, bezpiecznie backfilluj, zaostrz ograniczenia i usuń stare pole dopiero gdy masz dowód, że nikt od niego nie zależy.

Szybka lista przed wdrożeniem bezpieczniejszych migracji

Wizualizuj swój schemat najpierw
Projektuj tabele i relacje w Data Designer zanim dotkniesz danych produkcyjnych.
Wypróbuj

Gdy backend się regeneruje, kod może się szybko zmienić, ale produkcyjne dane nie wybaczą niespodzianek. Zanim wypuścisz zmianę schematu, przeprowadź krótki test "czy to może się bezpiecznie nie powieść?". To utrzymuje ewolucję schematu nudną — i o to chodzi.

5 kontroli, które łapią większość problemów

  • Rozmiar i szybkość backfillu: oszacuj, ile istniejących wierszy trzeba zaktualizować i ile to zajmie w produkcji. Backfill, który jest OK na małej bazie, może trwać godziny na realnych danych i spowolnić aplikację.
  • Ryzyko blokad i downtime: sprawdź, czy zmiana może zablokować zapisy. Niektóre operacje (alter dużej tabeli, zmiana typów) mogą trzymać blokady na tyle długo, by powodować timeouty. Jeśli jest szansa na blokadę, zaplanuj bezpieczniejszy rollout (najpierw nowa kolumna, potem backfill, na końcu zmiana kodu).
  • Kompatybilność starego kodu z nowym schematem: zakładaj, że stary backend może krótko działać przeciwko nowemu schematowi podczas deployu lub rollbacku. Zapytaj: czy poprzednia wersja nadal będzie czytać i zapisywać bez awarii? Jeśli nie, potrzebujesz dwustopniowego releasu.
  • Domyślne wartości i null-e: dla nowych kolumn zdecyduj, co się stanie z istniejącymi rekordami. Będą NULL, czy potrzebny jest default? Upewnij się, że logika traktuje brakujące wartości normalnie, zwłaszcza dla flag, statusów i timestampów.
  • Sygnały monitoringu do obserwacji: wybierz dokładne alarmy, na które będziesz patrzeć po wdrożeniu: współczynnik błędów API, wolne zapytania w DB, błędy kolejek/jobów oraz kluczowe akcje użytkowników (checkout, login, wysłanie formularza). Obserwuj też „ciche” błędy, jak skok w walidacjach.

Krótkie ćwiczenie praktyczne

Jeśli dodajesz nowe wymagane pole status do tabeli orders, nie wciskaj od razu "NOT NULL, bez defaultu". Najpierw dodaj pole jako nullable z domyślną wartością dla nowych wierszy, wdroż zregenerowany kod, który obsłuży brak statusu, potem backfilluj stare wiersze, a dopiero później zaostrz ograniczenia.

W AppMaster takie podejście jest szczególnie przydatne, bo backend można regenerować często. Traktuj każdą zmianę schematu jako mały release z łatwym rollbackem, a Twoje migracje pozostaną przewidywalne.

Przykład: ewolucja działającej aplikacji bez łamania istniejących rekordów

Przećwicz zmiany przed produkcją
Zmniejsz niespodzianki testując zmiany schematu na rzeczywistych kształtach danych przed release.
Zbuduj rozwiązanie

Wyobraź sobie narzędzie wewnętrzne, w którym agenci tagują zgłoszenia tekstowym polem priority (przykłady: "high", "urgent", "HIGH", "p1"). Chcesz przejść na ścisły enum, żeby raporty i reguły routingu przestały zgadywać.

Bezpieczne podejście to zmiana w dwóch releasach, która utrzymuje stare rekordy ważne podczas regeneracji backendu.

Release 1: rozszerz, zapisuj oba i backfilluj

Zacznij od rozszerzenia schematu bez usuwania czegokolwiek. Dodaj nowe pole enum, np. priority_enum z wartościami low, medium, high, urgent. Zachowaj oryginalne priority_text.

Następnie zaktualizuj logikę, żeby nowe i edytowane tickety zapisywały oba pola. W narzędziu bez kodu jak AppMaster zwykle oznacza to dostosowanie modelu w Data Designer i procesów biznesowych, by mapować wejście do enuma i równocześnie przechowywać oryginalny tekst.

Potem backfilluj istniejące tickety w małych partiach. Mapuj typowe teksty na enum ("p1" i "urgent" -> urgent, "HIGH" -> high). Wszystko nieznane tymczasowo mapuj na medium i oznacz do ręcznej weryfikacji.

Co widzą użytkownicy: najlepiej nic się nie zmienia. UI może dalej pokazywać ten sam kontroler priorytetu, ale w tle wypełniasz nowy enum. Raporty mogą zacząć korzystać z enuma już gdy backfill jest w toku.

Release 2: skurcz i usuń starą ścieżkę

Gdy masz pewność, przełącz odczyty na priority_enum, zaktualizuj filtry i dashboardy, a potem usuń priority_text w późniejszej migracji.

Przed Release 2 zwaliduj na małej próbce, żeby złapać edge case-y:

  • Wybierz 20–50 ticketów z różnych zespołów i lat.
  • Porównaj wartość widoczną dla użytkownika z wartością w enumie.
  • Sprawdź zliczenia po enumie, by wykryć podejrzane skoki (np. za dużo medium).

Jeśli pojawią się problemy, rollback jest prosty, bo Release 1 zachował stare pole: wdrożysz z powrotem logikę z Release 1 i ustawisz UI, by czytało z priority_text, podczas gdy poprawiasz mapowanie i ponownie uruchamiasz backfill.

Następne kroki: uczynij ewolucję schematu powtarzalnym nawykiem

Jeśli chcesz mieć przewidywalne migracje, traktuj zmiany schematu jak mały projekt, a nie szybki edit. Cel jest prosty: każdą zmianę powinno dać się łatwo wytłumaczyć, przećwiczyć i trudno przypadkowo zepsuć.

Wizualny model danych pomaga, bo ujawnia wpływ przed wdrożeniem. Gdy widzisz tabele, relacje i typy w jednym miejscu, zauważysz rzeczy, które łatwo przegapić w skrypcie — np. wymagane pole bez bezpiecznego defaultu albo relację, która spowoduje porzucenie rekordów.

Zrób szybkie „kto na tym polega?”: API, ekrany, raporty i joby w tle.

Gdy musisz zmienić pole, które już jest używane, preferuj krótki okres przejściowy z duplikacją pól. Na przykład dodaj phone_e164, zostaw phone_raw przez jedną lub dwie wersje. Zaktualizuj logikę, by czytać nowe pole, a gdy go nie ma — fallbackować do starego. Podczas przejścia zapisuj do obu pól, a stare usuń dopiero po weryfikacji pełnego backfillu.

Dyscyplina środowisk zamienia dobre intencje w bezpieczne releasy. Trzymaj dev, staging i produkcję spójnymi, ale nie traktuj ich jak identyczne.

  • Dev: upewnij się, że zregenerowany backend uruchamia się poprawnie i podstawowe przepływy działają po regeneracji.
  • Staging: uruchom pełen plan migracji na danych podobnych do produkcyjnych i zweryfikuj kluczowe zapytania, raporty i importy.
  • Produkcja: wdrażaj gdy masz plan rollback, jasny monitoring i mały zestaw testów "must pass".

Spisuj plan migracji, nawet krótko. Dołącz: co się zmienia, kolejność, jak backfill, jak weryfikować i jak wycofać. Potem przećwicz go end-to-end w środowisku testowym zanim dotknie produkcji.

Jeśli używasz AppMaster, wykorzystaj Data Designer do wizualnego rozumienia modelu i pozwól regeneracji utrzymać zgodność kodu z aktualnym schematem. Nawykiem, który utrzymuje przewidywalność, jest robienie migracji jawnie: możesz iterować szybko, ale każda zmiana ma zaplanowaną ścieżkę dla istniejących danych produkcyjnych.

Łatwy do uruchomienia
Stworzyć coś niesamowitego

Eksperymentuj z AppMaster z darmowym planem.
Kiedy będziesz gotowy, możesz wybrać odpowiednią subskrypcję.

Rozpocznij