Przejdź do treści
Architektura 7 min czytania

Monolit vs. microservices w e-commerce B2B - kiedy co

Microservices są drogie. To stwierdzenie powinno wisieć w każdej sali konferencyjnej, gdzie podejmuje się decyzje architektoniczne. Drogie w infrastrukturze (Kubernetes, observability, distributed tracing), drogie w utrzymaniu (więcej deploymentów, więcej awarii operacyjnych), drogie w debugowaniu (bug rozproszony po 5 serwisach). I uzasadnione tylko wtedy, gdy skala wymusza. Polski B2B 10-100 M zł obrotu - rzadko wymusza.

Jakub Owsianka Autor
Zaktualizowano:
Okladka artykulu: Monolit vs. microservices w e-commerce B2B - kiedy co (kategoria: Architektura)
Okladka artykulu: Monolit vs. microservices w e-commerce B2B - kiedy co (kategoria: Architektura)
Spis treści (7)

W skrócie

  • 1. Monolit = jedna aplikacja, jedna baza, jeden deployment. 95% polskich B2B w skali średniej.
  • 2. Modular monolith = monolit z dobrze odizolowanymi modułami. Może później ewoluować w microservices.
  • 3. Microservices = wiele małych aplikacji, każda z własną bazą i deploymentem.
  • 4. Decyzja: nie technologiczna, organizacyjna. Microservices opłacają się gdy masz 5+ niezależnych zespołów.
  • 5. Strangler fig = pattern wyodrębniania microservices z monolitu po jednym. Bezpieczna ścieżka, gdy skala faktycznie wymusi.

Co konkretnie znaczą te pojęcia

Klasyczny monolit:

  • Jedna aplikacja (Magento, Shopware, custom Symfony/Laravel)
  • Jedna baza danych (MySQL/Postgres)
  • Jeden proces deployment
  • Jeden zespół (lub kilka) pracuje w jednym repozytorium
  • Wszystko w pamięci jednego procesu

Magento Open Source, Shopware 6, PrestaShop - wszystkie monolity. Większość polskich sklepów B2B.

Modular monolith:

  • Jedna aplikacja, ale silnie modularna
  • Wewnętrzne moduły komunikują się tylko przez zdefiniowane interfejsy
  • Każdy moduł ma jasną odpowiedzialność
  • Wciąż jedna baza, jeden deployment
  • Łatwiejsza ewolucja w microservices jeśli kiedyś trzeba

To często złoty środek. Modular monolith ma zalety monolitu (prostota deploymentu, jedna baza) i przygotowanie do podziału.

Microservices:

  • Wiele małych aplikacji, każda jedna „bounded context"
  • Każdy serwis ma własną bazę
  • Każdy serwis ma własny deployment, własny cykl release
  • Komunikacja przez API (REST/GraphQL) lub message broker (Kafka, RabbitMQ)
  • Każdy serwis może być w innej technologii (PHP / Node / Go / Java)

Czysta architektura microservices w sklepie B2B: catalog service, cart service, checkout service, customer service, search service, inventory service, payment service. Każdy osobny.

Argumenty za microservices - i dlaczego rzadko ważą

1. Skala. Argument prawdziwy, ale tylko powyżej pewnego progu.

Microservices skalują się niezależnie. Catalog może mieć 20 nodów, checkout 5, search 30. W monolicie skalujesz wszystko razem.

Realny próg, gdzie to ma sens: ruch powyżej 10k req/s na peak'u, miliony zamówień rocznie. Polski B2B - rzadko (Allegro, Empik, x-kom - tak; średnia hurtownia - nie).

2. Niezależny rozwój zespołów.

5 zespołów = 5 release'ów dziennie bez konfliktów. W monolicie - release coupling, zespoły czekają na siebie.

Realny próg: 5+ niezależnych zespołów po 4-8 osób (czyli ~30-50 deweloperów w organizacji). Polski B2B w skali średniej - nigdy.

3. Technology diversity.

Catalog w PHP, checkout w Go, recommendations w Python. Każdy zespół wybiera swój stack.

Realny use case: rzadko sensowny. Większość firm i tak chce jednej technologii (łatwiej rotować deweloperów).

4. Niezależne wdrożenia ważnych zmian.

Refactor jednego serwisu bez ruszania całości. Mniejsze ryzyko każdego deploy.

Argumenty: w modular monolith też masz to (przy dobrej dyscyplinie modularności).

5. Resilience - awaria jednego serwisu nie kładzie wszystkiego.

Padł search? Sklep dalej działa (degraded mode). Padł checkout? Klienci dalej przeglądają.

Argument prawdziwy, ale wymaga: dobrego rozdzielenia danych, circuit breakerów, fallbacków. Niedbale zaprojektowane microservices są mniej resilient niż dobry monolit.

Argumenty przeciwko microservices

1. Złożoność operacyjna.

5 serwisów = 5 deployment'ów, 5 monitoringów, 5 logów, 5 dashboardów. Kubernetes obowiązkowy (lub odpowiednik), observability obowiązkowe.

2. Distributed transactions = piekło.

W monolicie zamówienie = transakcja DB, ACID. W microservices - saga pattern, eventual consistency, compensating transactions. Każda decyzja biznesowa wymaga przemyślenia.

3. Latencja sieciowa.

Każde wywołanie między serwisami = HTTP/gRPC, ~5-50ms. Pojedyncza akcja klienta (np. dodanie do koszyka) wywołuje 8 serwisów → +200ms over monolit.

4. Debugowanie rozproszone.

Bug pojawia się w produkcji. Distributed tracing pokazuje że request przeszedł przez 7 serwisów. Każdy ma własne logi. Łapanie buga zajmuje 4× dłużej.

5. Schema evolution.

Serwis catalog dodaje pole length. Serwisy konsumujące go muszą to przyjąć. Brak kompatybilności wstecznej = padają. Kontrakty, wersjonowanie, ostrożna ewolucja - to wszystko narzut.

6. Koszt infrastruktury.

5 serwisów × N replicas × Kubernetes cluster z observability = 5-10× więcej w hostingu vs. dobry monolit.

7. Czas wdrożenia.

Monolit MVP w 6 miesiącach. Microservices MVP w 12-18 miesięcy (więcej kompozycji, integracji, kontrak­tów do zaprojektowania).

Modular monolith - niedoceniana opcja

Modular monolith to monolit, w którym moduły są dyscyplinarnie odizolowane:

  • Każdy moduł ma jasną odpowiedzialność (Catalog, Cart, Checkout, Customer)
  • Moduły komunikują się tylko przez zdefiniowane interfejsy (porty/adaptery, DDD)
  • Każdy moduł ma własny schemat w bazie (logiczna separacja)
  • Refactor jednego modułu nie wymaga ruszania innych

Zalety:

  • Prostota deploymentu monolitu
  • Jedna baza, ACID transakcje
  • Ale lepsza struktura niż klasyczny "spaghetti monolith"
  • Łatwa ewolucja w microservices jeśli skala wymusi

Jak to robić w praktyce:

  • Symfony / Laravel z folder per moduł (src/Catalog/, src/Cart/, src/Customer/)
  • Każdy moduł = własny bounded context (DDD)
  • Komunikacja przez Event Bus (Symfony Messenger) lub direct interface calls
  • Schemat DB: namespace per moduł (catalog__products, cart__carts)

To dobre podejście dla nowych sklepów B2B w skali 20-100 M zł.

Strangler fig pattern - wyodrębnianie microservices

Klasyczny pattern z książki Martina Fowlera. Wyodrębniasz microservices z monolitu po jednym:

  1. Identyfikujesz bounded context który wymaga niezależnego skalowania
  2. Wystawiasz API w monolicie dla tego contextu (jeśli nie ma)
  3. Tworzysz nowy serwis który implementuje to API ale ma własną bazę
  4. Przekierowujesz traffic stopniowo z monolitu na nowy serwis (10%, 50%, 100%)
  5. Wyłączasz funkcję w monolicie po pełnej migracji

Bezpieczna ścieżka, gdy faktycznie skala wymusi. Można robić to przez 2-3 lata, serwis po serwisie.

Typowa kolejność dla sklepu:

  1. Search jako pierwszy (Elasticsearch/Algolia są naturalnie osobnym serwisem)
  2. Recommendations (jeśli istotne)
  3. Checkout (jeśli skala wymaga niezależnego skalowania)
  4. Customer / auth
  5. Pozostałe stopniowo

Kiedy microservices realnie

Realne progi z mojej praktyki:

1. 5+ niezależnych zespołów developerskich.

Każdy zespół po 4-8 osób, każdy odpowiada za swój domain. Co najmniej 30 deweloperów w organizacji.

2. Ruch produkcyjny powyżej 10k req/s na peak'u.

Skalowanie monolitu kosztowne, microservices skalują się niezależnie.

3. Multi-region z różnymi regulacjami.

Sklep PL + DE + UK + US, każdy z innymi politykami danych, innymi requirements (GDPR, CCPA, lokalne podatki).

4. Multi-brand z dzielonymi komponentami.

5 marek dzielących checkout, search, payment. Każda ze swoim UX, ale wspólnymi backendowymi funkcjami.

5. Wymóg niezależnego deployment'u krytycznych funkcji.

Checkout musi mieć release cycle inny niż katalog (np. weekendy = no-deploy dla checkout, dla katalogu OK).

Jeśli żadnego z tych warunków nie spełniasz - monolit (modular preferowany) jest lepszą decyzją.

Realny koszt - porównanie

Dla scenariusza: sklep B2B średniej skali (30k SKU, 5 M zamówień rocznie, 50 osób IT):

Monolit (modular) na Magento / Shopware:

  • Wdrożenie: 700 tys. - 1.5 mln zł
  • Hosting: 30-100 tys. zł / rok
  • Utrzymanie: 250-500 tys. zł / rok
  • Total roku 1: 1-2.1 mln zł
  • Total roku 3: 1.5-3.0 mln zł

Microservices custom (5-8 serwisów):

  • Wdrożenie: 2-4 mln zł (więcej projektowania, więcej kompozycji)
  • Hosting (Kubernetes, observability): 150-400 tys. zł / rok
  • Utrzymanie: 600-1200 tys. zł / rok
  • Total roku 1: 2.7-5.6 mln zł
  • Total roku 3: 3.9-7.2 mln zł

Microservices kosztują ~2.5× więcej dla średniego B2B. Bez konkretnego ROI (skala, multi-region, multi-brand) - to wydatek bez pokrycia.

FAQ

Czy mogę robić microservices na PHP? Tak, Symfony ma świetne wsparcie. Każdy serwis = osobna aplikacja Symfony z własną bazą. PHP nie jest tu blokerem.

Co z Kubernetes - must-have dla microservices? W praktyce tak. 5+ serwisów × N replicas + service discovery + autoscaling = potrzebujesz orchestratora. Można Docker Swarm dla mniejszych, ale Kubernetes to standard.

Czy mogę używać event sourcing w monolicie? Tak, modular monolith z event-driven design jest możliwy. Symfony Messenger + osobny moduł per domain + event bus = działa.

Czy „headless" oznacza „microservices"? Nie. Headless to wyodrębnienie frontu. Backend może być monolitem. Można mieć headless monolit (Magento + Next.js) lub headless microservices (commercetools + Next.js).

Kiedy zacząć rozważać strangler fig? Gdy monolit ma 3+ niezależne zespoły deweloperskie i jeden z bounded context'ów wymaga znacznie częstszych deployment'ów lub niezależnego skalowania.

Co dalej

O autorze

Jakub Owsianka

Architekt rozwiązania w WiseB2B - silniku platform B2B. Zaczynał po stronie biznesu (własne sklepy), potem deweloper, dziś projektuje wdrożenia dla sklepów z katalogami w dziesiątkach tysięcy SKU. W ostatnich latach wdrożył AI-development w zespole i funkcjonalności oparte o AI bezpośrednio w silniku sklepu.

Masz pytanie do tego artykułu?

Dodatkowy kontekst, problem z własnym wdrożeniem, druga opinia - napisz wprost. Odpowiadam osobiście w 1-2 dni robocze.