• Backend i DevOps
  • Strangler pattern w praktyce - jak migrować monolit etapami

Strangler pattern w praktyce - jak migrować monolit etapami

Jeremi Andrzejewski • 10 października 2026
Schemat pokazuje, jak nowy serwis powiadomień (Notification service) integruje się z istniejącym monolitem płatności, wykorzystując wzorzec strangler pattern do stopniowej migracji.

Spis treści

Gdy monolit obsługuje kluczowe procesy biznesowe, jego jednorazowe przepisanie zwykle oznacza miesiące ryzyka, kosztownych testów i presji ze strony użytkowników. Technika strangler pattern pozwala przeprowadzić taką modernizację etapami, kierując wybrane funkcje do nowych usług, podczas gdy reszta systemu nadal działa po staremu. Wyjaśniam, jak zaplanować migrację, gdzie umieścić warstwę routingu, jak podejść do danych oraz kiedy ten wzorzec ma sens w projekcie backendowym i DevOps.

Stopniowa migracja ogranicza ryzyko, ale wymaga dyscypliny

  • Istota wzorca polega na zastępowaniu monolitu małymi fragmentami funkcjonalności.
  • Fasada lub API Gateway kieruje żądania do starego albo nowego komponentu.
  • Dane są najtrudniejsze, szczególnie gdy oba systemy przez pewien czas zapisują ten sam obszar.
  • Najlepszy pierwszy moduł ma wyraźną granicę, ograniczone zależności i mierzalną wartość biznesową.
  • Pełna migracja kończy się dopiero po usunięciu zależności od monolitu, a nie po uruchomieniu pierwszego mikroserwisu.

Diagram ilustrujący wzorzec strangler: transformacja monolitu w mikroserwisy, koegzystencja i eliminacja.

Na czym polega wzorzec strangler fig

Nazwa nawiązuje do figowca dusiciela, który rośnie wokół istniejącego drzewa i stopniowo przejmuje jego przestrzeń. W architekturze oprogramowania nowa aplikacja rozwija się obok starej, a kolejne funkcje są wyprowadzane z monolitu aż do momentu, gdy stary system przestaje być potrzebny.

W praktyce klient nie musi wiedzieć, czy obsługuje go monolit, czy nowa usługa. Przed obiema częściami stawia się warstwę pośrednią, na przykład reverse proxy, API Gateway albo własną fasadę aplikacyjną. To ona rozpoznaje ścieżkę, typ operacji lub kontekst użytkownika i przekazuje żądanie do właściwego miejsca.

Etap Obsługa ruchu Cel
Start Prawie cały ruch trafia do monolitu Wprowadzenie routingu bez zmiany zachowania systemu
Pierwsza migracja Wybrane endpointy obsługuje nowa usługa Sprawdzenie granic domeny i sposobu wdrożenia
Rozwój Coraz więcej funkcji działa poza monolitem Zmniejszanie odpowiedzialności starej aplikacji
Finisz Całość działa w nowym systemie Wyłączenie monolitu i zbędnej fasady

Ten model nie oznacza automatycznie, że kończymy z mikroserwisami. Można w ten sposób przejść z aplikacji Django do kilku usług FastAPI, ale równie dobrze wyodrębnić moduły w drugim, lepiej uporządkowanym monolicie. Celem jest bezpieczna wymiana odpowiedzialności, a nie samo rozmnożenie procesów i repozytoriów.

Dlaczego migracja etapami bywa lepsza od wielkiego przepisywania

Jednorazowy rewrite wygląda atrakcyjnie na diagramie, lecz długo nie dostarcza wartości. Przez wiele miesięcy zespół buduje nową wersję, a użytkownicy nadal korzystają ze starej. Problem pojawia się na końcu, gdy trzeba jednocześnie porównać zachowanie obu systemów, przenieść dane i wykonać przełączenie bez pewności, że odtworzono wszystkie ukryte reguły biznesowe.

Stopniowa wymiana pozwala dostarczać funkcje wcześniej i ogranicza rozmiar pojedynczej zmiany. Gdy nowy moduł zamówień działa poprawnie, można obserwować go na produkcji, zebrać metryki i dopiero wtedy wybrać następny fragment. Z mojego punktu widzenia największą zaletą jest krótsza pętla informacji zwrotnej, nie samo hasło „mniejsze ryzyko”.

Trzeba jednak zapłacić za okres współistnienia dwóch światów. Przez pewien czas utrzymujemy podwójny koszt operacyjny, dodatkowe integracje, monitoring i procedury awaryjne. Nowa usługa może być prostsza od monolitu, ale cała architektura migracyjna często staje się przejściowo bardziej skomplikowana.

Podejście Największa korzyść Główne ryzyko Kiedy rozważyć
Stopniowa wymiana Małe, odwracalne kroki Długie utrzymywanie dwóch systemów System krytyczny, który musi działać bez przerwy
Jednorazowy rewrite Spójna architektura od pierwszego dnia Duży, późno wykryty błąd migracji Mała aplikacja, dobry zakres i krótki termin przełączenia
Refaktoryzacja monolitu Mniej infrastruktury i integracji Wolniejsza separacja zespołów i wdrożeń Gdy problemem jest głównie kod, a nie skalowanie domen

Jak zaplanować pierwszy fragment do wycięcia

Najczęstszy błąd polega na rozpoczęciu od największego i najbardziej strategicznego modułu. Lepiej wybrać funkcję, która ma jasne wejścia i wyjścia, nie zmienia kilkunastu tabel naraz i pozwala szybko sprawdzić, czy przyjęta architektura działa.

Znajdź granicę domeny

Dobrym kandydatem może być katalog produktów, generowanie raportów, powiadomienia albo obsługa płatności, zależnie od systemu. Nie patrzę wyłącznie na nazwę modułu. Sprawdzam, kto zapisuje dane, jakie procesy wywołują daną funkcję i czy reguły biznesowe nie są rozsiane po całym kodzie.

Przed rozpoczęciem prac warto przygotować mapę zależności oraz pomiary bazowe. Powinna obejmować między innymi czas odpowiedzi, liczbę błędów, obciążenie bazy i wolumen żądań. Bez tych danych po migracji trudno odróżnić realną poprawę od wrażenia, że nowa usługa jest „nowocześniejsza”.

Ustal kryteria zakończenia

Każdy etap powinien mieć warunek wyjścia, na przykład brak krytycznych rozbieżności danych przez 14 dni, błędy poniżej ustalonego progu i możliwość odtworzenia poprzedniej ścieżki w kilka minut. To nie są uniwersalne liczby, ale konkretne kryteria chronią projekt przed niekończącym się okresem „jeszcze tylko jednej poprawki”.

W przypadku aplikacji Python często zaczynam od wydzielenia kontraktu HTTP, testów akceptacyjnych i osobnego pakietu domenowego. Dopiero później przenoszę kod do niezależnego procesu. Dzięki temu najpierw sprawdzam granicę odpowiedzialności, a technologia nie zasłania problemu architektonicznego.

Routing, dane i wdrożenia decydują o powodzeniu

Sama fasada nie rozwiązuje migracji. Musi wiedzieć, dokąd wysłać żądanie, jak obsłużyć timeout i co zrobić, gdy nowa usługa zwróci błąd. W prostym wariancie reguły mogą działać na poziomie ścieżki, na przykład /orders kierować do nowego backendu, a /reports pozostawić w monolicie.

Przy bardziej ryzykownych zmianach przydają się feature flags, czyli przełączniki pozwalające aktywować nową implementację dla wybranej grupy użytkowników. Można zacząć od ruchu wewnętrznego, potem przejść do 1%, 10% i 50%, o ile metryki pozostają stabilne. Procenty są przykładowe, lecz zasada jest stała: zwiększaj ekspozycję dopiero po sprawdzeniu obserwowalności.

Nie pozwól, aby dwa systemy dowodziły tym samym

Najbezpieczniej ustalić, który komponent jest źródłem prawdy dla konkretnej domeny. Współdzielona baza ułatwia start, ale utrwala sprzężenie. Osobna baza dla nowej usługi daje większą niezależność, za to wymaga migracji danych, synchronizacji i obsługi chwilowych rozbieżności.

Podwójny zapis, czyli wysyłanie tej samej zmiany do starego i nowego systemu, może być potrzebny przejściowo, lecz jest podatny na częściowe niepowodzenia. Przy większej skali rozsądniejsza bywa synchronizacja zdarzeniowa lub CDC, czyli przechwytywanie zmian w bazie i przekazywanie ich do drugiego magazynu. W obu wariantach trzeba mieć proces uzgadniania oraz możliwość ponowienia operacji.

Przeczytaj również: Mikroserwisy - Kiedy warto i jak je wdrożyć? Poradnik.

Warstwa antykorupcyjna chroni nowy kod

Stary system często używa nazw i modeli, których nie chcemy przenosić do nowej usługi. Anti-corruption layer tłumaczy te pojęcia na model nowej domeny, dzięki czemu mikroserwis nie zaczyna zależeć od dziwnych statusów, skrótów i wyjątków odziedziczonych po monolicie.

Od strony DevOps potrzebne są osobne logi, metryki i ślady żądań dla obu ścieżek. Warto rejestrować identyfikator korelacyjny, wersję obsługującej usługi, czas odpowiedzi oraz powód routingu. Bez distributed tracing, czyli śledzenia jednego żądania przez wiele usług, diagnoza problemu szybko zamienia się w zgadywanie.

Praktyczny przebieg migracji od analizy do wyłączenia monolitu

Proces można przeprowadzić w kilku powtarzalnych iteracjach. Każda powinna kończyć się działającym, obserwowalnym fragmentem, a nie wyłącznie kodem oczekującym na wielkie przełączenie.

  1. Opisz stan obecny. Zidentyfikuj endpointy, zadania asynchroniczne, tabele, integracje i reguły biznesowe. Zaznacz miejsca, w których brakuje testów.
  2. Wprowadź punkt wejścia. Skieruj ruch przez reverse proxy lub gateway, ale na początku zachowaj dotychczasowe zachowanie aplikacji.
  3. Wybierz jeden pionowy wycinek. Przenieś całą funkcję wraz z API, logiką, testami i obsługą błędów, zamiast wyciągać tylko warstwę prezentacji.
  4. Ustal właściciela danych. Zdecyduj, gdzie wykonywane są zapisy i jak pozostałe komponenty otrzymują aktualizacje.
  5. Włącz kontrolowany ruch. Użyj flagi funkcjonalnej, canary release albo routingu dla konkretnego klienta.
  6. Porównuj wyniki. Testy kontraktowe, shadow traffic i audyt rozbieżności pokażą problemy, których nie widać w testach jednostkowych.
  7. Usuń stare zależności. Dopiero po stabilizacji skasuj nieużywane endpointy, kod, tabele i procesy synchronizacji.

Przełączenie powinno być odwracalne tak długo, jak długo istnieje stary model danych. Po usunięciu tabel i procedur powrót może wymagać odtworzenia struktur oraz ponownego odegrania zmian, dlatego kasowanie legacy należy traktować jako osobny etap ryzyka, a nie sprzątanie po migracji.

W pipeline CI/CD sprawdzam co najmniej testy kontraktowe, migracje schematu, skanowanie zależności i automatyczny rollback obrazu. Dobrze działa też krótka lista kontrolna przed zwiększeniem ruchu, obejmująca p95 czasu odpowiedzi, błędy 5xx, opóźnienie synchronizacji i zgodność kluczowych rekordów.

Kiedy ten wzorzec nie będzie dobrym wyborem

Stopniowa migracja ma sens, gdy monolit może działać jeszcze przez wiele miesięcy, ruch da się przechwycić, a zespół ma dostęp do kodu i danych. Jeśli trzeba wyłączyć stary system w ciągu kilku tygodni, budowanie przejściowej fasady może tylko odsunąć problem i zwiększyć koszt.

Odradzałbym ten model także wtedy, gdy aplikacja jest mała, a jej pełne zastąpienie zajmie kilka sprintów. W takim przypadku prosty rewrite lub refaktoryzacja będzie tańsza niż utrzymywanie gatewaya, dwóch wdrożeń i mechanizmu synchronizacji.

Ryzyko rośnie, gdy jedna operacja biznesowa obejmuje wiele domen i wymaga transakcji między systemami. Można wtedy zastosować komunikację asynchroniczną, sagę albo etap pośredni, ale każda z tych technik zwiększa złożoność. Nie warto udawać, że rozdzielenie procesu na mikroserwisy zachowa za darmo atomowość znaną ze wspólnej transakcji SQL.

Najbardziej zdradliwy jest etap, w którym przeniesiono 70-80% funkcji, lecz pozostała reszta zawiera najstarsze reguły i najwięcej wyjątków. Ustalenie budżetu, właściciela oraz orientacyjnego terminu wyłączenia monolitu już na początku pomaga uniknąć sytuacji, w której architektura przejściowa staje się stałym rozwiązaniem.

Jak rozpoznać, że migracja naprawdę dobiegła końca

Uruchomienie nowego mikroserwisu nie jest jeszcze sukcesem migracji. Za zakończenie uznaję dopiero moment, gdy nowy komponent ma własność nad swoją domeną, monolit nie wykonuje już ukrytych zapisów, a zespół potrafi odtworzyć proces wdrożenia i awarii bez ręcznych, nieudokumentowanych czynności.

Przed usunięciem fasady sprawdziłbym trzy rzeczy: brak ruchu do starej ścieżki, brak zależności w kodzie i logach oraz poprawność danych po okresie obserwacji. Dopiero wtedy można wyłączyć routing przejściowy, archiwizować stare zasoby i uprościć infrastrukturę.

Najważniejsza lekcja jest prosta. Ten wzorzec nie zastępuje analizy domeny, testów ani dobrego modelu danych, lecz pozwala rozłożyć trudną decyzję na mniejsze decyzje. Gdy każdy etap ma jasny zakres, metryki i plan odwrotu, modernizacja monolitu przestaje być skokiem w nieznane, a staje się serią kontrolowanych zmian.

FAQ - Najczęstsze pytania

Najlepszy pierwszy fragment ma jasne wejścia i wyjścia, ograniczone zależności oraz mierzalną wartość biznesową. Przed migracją warto sprawdzić, kto zapisuje dane, jakie procesy wywołują funkcję i jakie są bazowe metryki, takie jak czas odpowiedzi, błędy, obciążenie bazy i wolumen żądań.

Przed monolitem i nowymi usługami należy umieścić warstwę pośrednią, na przykład reverse proxy, API Gateway lub fasadę aplikacyjną. Może ona kierować ruch według ścieżki, typu operacji, użytkownika albo feature flagi, a także obsługiwać timeouty i błędy nowej usługi.

Dla każdej domeny trzeba wskazać jedno źródło prawdy. Podwójny zapis może być rozwiązaniem przejściowym, ale wymaga obsługi częściowych błędów; przy większej skali można zastosować synchronizację zdarzeniową lub CDC oraz proces uzgadniania i ponawiania zmian.

Wzorzec nie opłaca się zwykle przy małej aplikacji, którą można zastąpić w kilka sprintów, ani wtedy, gdy stary system musi zostać wyłączony w ciągu kilku tygodni. Ryzyko rośnie również przy operacjach obejmujących wiele domen i wymagających transakcji między systemami.

Oceń artykuł

Ocena: 0.00 Liczba głosów: 0

Tagi

monolit
mikroserwisy
feature flags
cdc
api gateway
Autor Jeremi Andrzejewski
Jeremi Andrzejewski
Nazywam się Jeremi Andrzejewski i od 13 lat zajmuję się programowaniem, w szczególności w języku Python oraz nowoczesnymi technologiami. Moje zainteresowanie tymi tematami zaczęło się od pierwszych projektów, które realizowałem w szkole, a z czasem przerodziło się w pasję do rozwiązywania problemów i tworzenia innowacyjnych rozwiązań. Lubię dzielić się swoją wiedzą, szczególnie w zakresie analizy danych, automatyzacji procesów oraz tworzenia aplikacji webowych. W swojej pracy koncentruję się na dostarczaniu użytecznych, klarownych i aktualnych informacji. Staram się zawsze sprawdzać źródła, porównywać dostępne informacje i upraszczać skomplikowane zagadnienia, aby były zrozumiałe dla każdego. Wierzę, że odpowiednie zorganizowanie wiedzy oraz śledzenie najnowszych trendów w branży są kluczowe dla efektywnego nauczania i rozwoju. Cieszę się, że mogę dzielić się swoimi doświadczeniami na akademiapython.pl, gdzie mam nadzieję inspirować innych do odkrywania fascynującego świata programowania.

Udostępnij artykuł

Napisz komentarz