Microservices architecture: jak projektować i utrzymywać system rozproszony
Microservices architecture to sposób budowy systemu, w którym jedna aplikacja zostaje rozbita na kilkanaście lub kilkadziesiąt niezależnie wdrażanych usług. Dobrze zaprojektowana microservices architecture pozwala zespołowi wypuszczać zmiany w koszyku zakupowym bez ruszania modułu płatności, a awaria generatora raportów nie zabiera ze sobą całego sklepu. Cena tej elastyczności jest realna: rośnie liczba repozytoriów, pipeline’ów CI, kolejek, certyfikatów i alertów, które ktoś musi utrzymać. Zanim podzielisz monolit, policz, ile procesów naprawdę potrzebujesz i czy zespół udźwignie ich obsługę. Ten tekst pokazuje, jak wyznaczać granice usług, jak wybrać model komunikacji, ile kosztuje infrastruktura w złotówkach i w których sytuacjach rozbicie systemu przynosi więcej szkody niż pożytku. Punktem odniesienia są typowe projekty polskich zespołów: sklepy z feedem produktowym, portale treściowe oraz platformy SaaS obsługujące kilkaset tysięcy żądań dziennie. Zamiast teorii dostajesz liczby, progi decyzyjne i konkretne konfiguracje, które da się odtworzyć u siebie.
Mikroserwisy a monolit: gdzie przebiega prawdziwa granica
Monolit nie jest wadą architektoniczną, tylko decyzją o wspólnym cyklu wdrożeniowym. Problem zaczyna się wtedy, gdy jeden zespół blokuje wydanie drugiego, a testy regresyjne trwają trzy godziny. Rozbicie systemu ma sens dopiero wtedy, gdy koszt koordynacji przewyższa koszt utrzymania dodatkowych procesów, kolejek i kontraktów API.
Kluczowa różnica dotyczy danych. W monolicie moduł raportów sięga bezpośrednio do tabeli zamówień, więc zmiana schematu wywraca pół aplikacji. Usługa autonomiczna trzyma własny schemat i udostępnia go wyłącznie przez API lub zdarzenia, co kosztuje więcej kodu, ale eliminuje ukryte sprzężenia między zespołami pracującymi w różnym tempie.
Firmy, których specjalnością jest projektowanie stron internetowych, dzielą system prościej: warstwa prezentacji renderuje treść, a osobna usługa obsługuje formularze i integracje. Taki podział chroni czas odpowiedzi, co bezpośrednio wpływa na pozycjonowanie strony, bo Core Web Vitals mierzą realne opóźnienia, nie deklaracje z dokumentacji technicznej.
Granice usług według domeny, nie według warstwy
Najczęstszy błąd to podział na usługę bazodanową, usługę logiki i usługę widoku. Taki układ tworzy trzy procesy, które zawsze wdraża się razem. Granicę wyznaczaj wokół zdolności biznesowej: katalog, koszyk, płatności, wysyłka. Każda z nich ma inny rytm zmian, inny profil ruchu i inne wymagania dostępności.
Komunikacja między usługami: REST, gRPC czy zdarzenia
Synchroniczne wywołanie REST jest proste w debugowaniu, ale łączy dostępność usług: jeśli katalog odpowiada w 400 ms, a koszyk czeka na niego przy każdym żądaniu, sumujesz opóźnienia i ryzyka. gRPC skraca narzut serializacji, jednak nie usuwa fundamentalnego sprzężenia czasowego między procesami.
Komunikacja zdarzeniowa odwraca zależność. Usługa zamówień publikuje fakt „zamówienie opłacone”, a subskrybenci reagują we własnym tempie. RabbitMQ obsłuży kilka tysięcy wiadomości na sekundę na jednym węźle, Kafka skaluje się do setek tysięcy, ale wymaga świadomej pracy z partycjonowaniem, retencją i kolejnością zdarzeń.
Kontrakty wymagają wersjonowania od pierwszego dnia. W projektach headless, gdzie panel redakcyjny i strona publiczna są rozdzielone, endpoint odpowiadający za wordpress logowanie zostaje w starym CMS-ie, a frontend konsumuje wyłącznie API treści. Zmiana pola w odpowiedzi bez wersji potrafi wygasić kilka integracji naraz.
Wybór narzędzia zaczynaj od wolumenu. Do dziesięciu tysięcy komunikatów dziennie wystarczy kolejka na Redisie lub RabbitMQ w wersji zarządzanej. Powyżej miliona zdarzeń dziennie i przy wymogu odtwarzania historii sensowna staje się Kafka, choć utrzymanie klastra to dodatkowy etat albo usługa zarządzana.
Infrastruktura i koszty: ile realnie kosztuje utrzymanie
Trzy usługi zmieszczą się na jednej maszynie. Przy dwunastu potrzebujesz orkiestratora, rejestru obrazów i sensownej sieci. Klaster oparty o ovh vps z 8 GB RAM startuje od kilkudziesięciu złotych miesięcznie za instancję, więc trzy węzły robocze plus baza to wydatek rzędu 300-500 zł miesięcznie.
Do rachunku dolicz narzędzia. Rejestr obrazów, monitoring, backupy i poczta firmowa potrafią przekroczyć koszt samych serwerów, a google workspace cena zaczyna się od kilkudziesięciu złotych za użytkownika miesięcznie, więc przy dziesięcioosobowym zespole to kolejne kilkaset złotych w budżecie utrzymania. Bez tej pozycji estymacja zawsze wychodzi zbyt optymistycznie.
| Element infrastruktury | Wariant startowy | Koszt orientacyjny (PLN/mies.) |
|---|---|---|
| Węzły aplikacyjne | 3 x VPS 4 vCPU / 8 GB | 240-450 |
| Baza danych | PostgreSQL z repliką odczytu | 150-400 |
| Broker wiadomości | RabbitMQ na osobnej instancji | 60-180 |
| Monitoring i logi | Prometheus, Grafana, retencja 30 dni | 80-350 |
| Rejestr obrazów i backupy | 200 GB przestrzeni obiektowej | 40-120 |
Integracje zewnętrzne zasługują na osobne usługi, bo mają własny reżim limitów i awarii. Eksport oferty do google merchant wymaga cyklicznego przeliczania feedu, walidacji GTIN i obsługi odrzuceń, a trzymanie tego w procesie obsługującym ruch użytkowników kończy się zapchanym wątkiem w szczycie sprzedaży.
Stanowisko pracy zespołu też jest pozycją w budżecie
Rozproszony system oznacza pracę na wielu terminalach, logach i dashboardach naraz. Drugi monitor do komputera w rozdzielczości 2560×1440 kosztuje 700-1200 zł i zwraca się szybciej niż niejedno narzędzie SaaS. Wygodna klawiatura mechaniczna z przełącznikami liniowymi to wydatek 300-600 zł przy ośmiu godzinach pisania kodu dziennie.

Przy ciasnym biurku sprawdza się klawiatura mechaniczna 60 procent, choć brak bloku nawigacyjnego bywa uciążliwy podczas pracy z długimi logami. Klawiatura gamingowa mechaniczna z podświetleniem RGB nie daje przewagi w terminalu, a tablet graficzny wacom przyda się raczej projektantom rysującym diagramy architektury niż inżynierom backendu.
Obserwowalność, testowanie i odporność na awarie
Bez telemetrii rozproszony system staje się zgadywanką. Minimalny zestaw to metryki w Prometheusie, logi zbierane centralnie oraz śledzenie rozproszone w standardzie OpenTelemetry. Identyfikator korelacji musi przechodzić przez każdą granicę usługi, inaczej odtworzenie ścieżki jednego zamówienia zajmie pół dnia zamiast dwóch minut.
Testy jednostkowe nie wykryją niezgodności kontraktu. Testy kontraktowe w stylu consumer-driven, uruchamiane w pipelinie każdej usługi, wyłapują zmianę pola zanim trafi na produkcję. Do tego dochodzi środowisko integracyjne z kontenerami startowanymi na żądanie, bo mockowanie wszystkiego daje fałszywe poczucie bezpieczeństwa.
Odporność projektuje się jawnie. Limity czasu na każde wywołanie sieciowe, wyłącznik obwodu po serii błędów, ponowienia z wykładniczym opóźnieniem oraz idempotentne operacje zapisu to cztery mechanizmy, bez których jedna wolna usługa potrafi wyczerpać pulę połączeń w całym klastrze w kilkadziesiąt sekund.
- Limit czasu 2-5 sekund na każde wywołanie między usługami
- Wyłącznik obwodu otwierany po 50 procent błędów w oknie minuty
- Kolejka martwych wiadomości z alertem po pierwszym wpisie
- Health check gotowości oddzielony od health checku żywotności
- Wersjonowanie API w ścieżce, ze wsparciem starej wersji minimum sześć miesięcy
Ustal budżet błędu dla każdej usługi. Jeśli koszyk ma dostępność 99,9 procent, masz około 43 minut przestoju miesięcznie i to jest limit, w którym mieszczą się wdrożenia, migracje i incydenty. Bez takiego progu każda dyskusja o jakości kończy się wymianą opinii zamiast decyzją.
Kiedy microservices architecture się nie opłaca
Nie każdy projekt zyskuje na podziale. Zespół pięcioosobowy utrzymujący jedną aplikację o stałym ruchu spędzi więcej czasu na konfiguracji klastra niż na funkcjach dla klienta. Modularny monolit z wyraźnymi granicami pakietów daje około 80 procent korzyści przy ułamku kosztu operacyjnego.
Serwisy treściowe to osobny przypadek. Renderowanie po stronie serwera z jednego procesu bywa szybsze niż łańcuch wywołań między trzema usługami, a pozycjonowanie strony w google premiuje stabilny czas odpowiedzi i przewidywalny HTML. Podział na mikroserwisy dokładaj tu dopiero przy wyraźnie różnych profilach obciążenia.
Drugi sygnał ostrzegawczy to rozlana transakcyjność. Jeśli jedna operacja biznesowa wymaga spójnego zapisu w czterech usługach, wchodzisz w sagi, kompensacje i stany pośrednie. To działa, ale kosztuje kilka razy więcej kodu niż jedna transakcja bazodanowa i generuje klasę błędów trudnych do odtworzenia.
Podział techniczny bez podziału organizacyjnego kończy się rozproszonym monolitem: usług jest dwanaście, ale każde wdrożenie trzeba zsynchronizować. Jeśli struktura zespołów nie odwzorowuje granic usług, zyskujesz wyłącznie narzut sieciowy. Prawo Conwaya działa niezależnie od tego, czy ktoś uwzględnił je w projekcie.
Jak przeprowadzić migrację z monolitu do mikroserwisów?
Zacznij od wzorca duszącego figowca: nowe funkcje buduj jako osobne usługi, a ruch kieruj przez bramę, która stopniowo przejmuje kolejne ścieżki od monolitu. Pierwszym kandydatem do wydzielenia jest moduł o największej częstotliwości zmian albo najcięższym obciążeniu, zwykle wyszukiwarka, generator raportów lub integracja z systemem zewnętrznym. Przed przeniesieniem kodu rozdziel dane: skopiuj tabele, uruchom podwójny zapis, porównaj wyniki przez dwa tygodnie i dopiero potem odetnij stare źródło. Każdy krok musi mieć plan wycofania oraz mierzalny cel, na przykład skrócenie czasu wdrożenia z czterdziestu minut do pięciu. Wydzielenie jednego modułu zajmuje w praktyce od trzech do ośmiu tygodni pracy dwóch osób.
Czy microservices architecture ma sens w małym projekcie?
Rzadko. Przy zespole liczącym mniej niż osiem osób koszt utrzymania klastra, pipeline’ów i monitoringu zjada czas, który mógłby pójść na funkcje dla użytkowników. Sensowniejszy jest modularny monolit: jeden proces, jedno wdrożenie, ale wyraźne granice modułów, osobne schematy w bazie i zakaz sięgania do cudzych tabel. Taka struktura pozwala wydzielić usługę później, bez przepisywania logiki od zera. Wyjątkiem są sytuacje, w których jeden fragment ma radykalnie inny profil pracy: przetwarzanie wideo, generowanie plików PDF czy odpytywanie zewnętrznego API z twardym limitem żądań. Wtedy wydziela się pojedynczą usługę, a nie całą architekturę rozproszoną, i utrzymuje resztę systemu w jednym procesie.
Co generuje największe ukryte koszty w mikroserwisach?
Największe koszty nie leżą w serwerach, tylko w utrzymaniu. Każda nowa usługa dokłada repozytorium, pipeline, zestaw sekretów, certyfikaty, alerty, dokumentację API oraz dyżur. Przy dwudziestu usługach aktualizacja jednej biblioteki bezpieczeństwa to dwadzieścia pull requestów, chyba że zbudujesz automatyzację, która sama kosztuje kilka tygodni pracy. Drugą pozycją jest debugowanie: znalezienie przyczyny błędu wymaga korelacji logów z kilku procesów, więc bez śledzenia rozproszonego czas rozwiązania incydentu rośnie kilkukrotnie. Trzecia to onboarding, bo nowa osoba potrzebuje tygodni, żeby zrozumieć przepływ danych między usługami. Realny narzut operacyjny w dojrzałym systemie pochłania zwykle 20-30 procent czasu zespołu.
