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.
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, kontraktó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:
- Identyfikujesz bounded context który wymaga niezależnego skalowania
- Wystawiasz API w monolicie dla tego contextu (jeśli nie ma)
- Tworzysz nowy serwis który implementuje to API ale ma własną bazę
- Przekierowujesz traffic stopniowo z monolitu na nowy serwis (10%, 50%, 100%)
- 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:
- Search jako pierwszy (Elasticsearch/Algolia są naturalnie osobnym serwisem)
- Recommendations (jeśli istotne)
- Checkout (jeśli skala wymaga niezależnego skalowania)
- Customer / auth
- 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
- Headless commerce: Headless dla B2B
- Komunikacja między serwisami: Kolejki RabbitMQ / Redis
- Skalowanie bazy: Skalowanie DB
- Platformy gotowe: Platformy B2B
- Pillar architektury: Architektura dużych sklepów
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.