Od szaf z lampami do współczesnej chmury – kontekst historyczny
Gdzie zaczyna się opowieść o dekompozycji systemów
Gdy pierwszy raz ktoś widzi zdjęcia komputerów z lat 50. – ogromne szafy pełne lamp elektronowych, kilometry kabli, operatorzy w białych kitlach – trudno uwierzyć, że to bezpośredni przodkowie współczesnych mikroserwisów i chmury. A jednak łączy je wspólna oś: rosnąca złożoność systemów informatycznych i nieustanne próby podziału tej złożoności na części, które da się zrozumieć, zaprojektować i utrzymać.
Na początku dominowała prostota wymuszona fizyką i technologią. Jeden komputer, jedno pomieszczenie, jeden zespół. Z czasem, gdy komputerów i użytkowników przybywało, a biznes zaczął opierać się na danych, pojawiła się konieczność dzielenia systemów – najpierw sprzętowo, potem logicznie, później domenowo. Dekompozycja systemów IT nie jest wynalazkiem epoki mikroserwisów; to raczej długo ewoluująca odpowiedź na pytanie: jak utrzymać rosnący system, który nigdy nie przestaje się zmieniać?
W każdej epoce ograniczenia były inne. W mainframe’ach hamulcem była cena sprzętu i pamięci, w erze PC – sieć, w epoce webu – wydajność serwerów aplikacyjnych, w chmurze – złożoność architektury i koszt operacyjny. Styl architektury był więc ściśle związany z tym, co w danym czasie było najdroższe i najtrudniejsze: sprzęt, praca ludzi czy koordynacja rozproszonych elementów.
Dekompozycja jako odpowiedź na rosnącą złożoność
Jeżeli system ma przetrwać dłużej niż parę lat, musi ewoluować razem z organizacją. Pojawiają się nowe procesy, nowe produkty, kolejne regulacje, a wraz z nimi – kolejne funkcje, tabele, moduły i integracje. Bez świadomej dekompozycji kończy się to jednym: monolitem, którego boi się dotknąć każdy programista. Historia architektury IT jest historią kolejnych sposobów ucieczki przed takim kolosem.
Od mainframe’ów do mikroserwisów przewija się kilka powtarzalnych motywów:
- centralizacja vs. decentralizacja – czy lepiej mieć jeden silny system, czy wiele mniejszych współpracujących;
- podział odpowiedzialności – kto za co odpowiada: zespół, moduł, serwis, usługa;
- granice – czy system dzielimy według technologii, warstw, czy domen biznesowych;
- integracja – jak poszczególne części rozmawiają ze sobą: pliki, kolejki, API, ESB, eventy.
U podstaw każdej nowej mody architektonicznej stoi bardzo przyziemny problem: zespoły nie nadążają z rozumieniem całości, a każda zmiana niesie ryzyko awarii. Dekompozycja systemów IT jest więc próbą rozbicia tego ryzyka na mniejsze kawałki – takie, które da się objąć ludzką głową.
Od mainframe’ów do mikroserwisów – krótki przegląd epok
Przeskakując przez dekady, można zauważyć wyraźne „kamienie milowe” w ewolucji architektury monolitycznej w stronę systemów rozproszonych i mikroserwisów:
- Era mainframe’ów – jeden wielki komputer, przetwarzanie wsadowe, terminale jako „cienki klient”. Logika biznesowa i dane w jednym, monolitycznym środowisku.
- Minikomputery – tańsze maszyny w działach i oddziałach, rozproszenie obliczeń, narodziny myślenia modułowego.
- Rewolucja PC – komputery na biurkach, lokalne aplikacje, sieci LAN, architektura klient–serwer.
- Web i trójwarstwowość – przeglądarka jako uniwersalny klient, serwery aplikacyjne, pierwsze poważne systemy rozproszone w biznesie.
- SOA i ESB – usługi biznesowe, integracja przez centralny bus, próba uporządkowania wielu aplikacji w organizacji.
- Chmura i mikroserwisy – dekompozycja domenowa, małe, niezależnie wdrażalne serwisy, automatyzacja i ciągła dostawa.
W tle trwa nieustanny dialog między „wszystko w jednym miejscu” a „wiele małych klocków”. Jeśli zna się tę historię, dużo łatwiej dostrzec, kiedy mikroserwisy są rozsądnym krokiem naprzód, a kiedy tylko powtórką dawnych błędów w nowym opakowaniu.
Era mainframe’ów – kiedy „system” znaczył jeden komputer
Architektura centralna i „grube” centrum wszechświata
Pierwsze systemy informatyczne były niemal karykaturalnie proste pod względem architektury: jeden potężny komputer, jedna pamięć, jeden system operacyjny. Cała złożoność kryła się w tym, żeby maszyna w ogóle działała – lampy elektronowe się przepalały, pamięć była liczoną w kilobajtach rzadkością, a dane trzymano na taśmach magnetycznych.
Użytkownicy nie mieli kontaktu z komputerem w dzisiejszym sensie. Zamiast tego przygotowywali zadania w formie kart perforowanych lub taśm, które trafiały do operatorów. Ci ładowali wsad, uruchamiali przetwarzanie, a użytkownik po jakimś czasie odbierał wyniki na wydruku. Model przetwarzania wsadowego nie sprzyjał interakcyjności, ale miał jedną zaletę: architektura systemu była niemal w całości monolityczna.
Programy pisano najczęściej w jednym środowisku (np. COBOL dla systemów bankowych), na jednym typie sprzętu. Nie było rozproszonych komponentów, skomplikowanych integracji ani wielopoziomowych warstw. „System bankowy” oznaczał fizycznie zainstalowane oprogramowanie na jednym mainframie, a cała organizacja była od niego zależna.
Monolit jako naturalna konsekwencja ograniczeń
Dzisiejsze narzekania na monolity mają inny kontekst. W erze mainframe’ów monolit był po prostu racjonalną odpowiedzią na ograniczenia:
- sprzęt był ekstremalnie drogi, więc nikt nie myślał o duplikowaniu funkcji na kilku maszynach;
- pamięć była skrajnie ograniczona, co premiowało jednolity kod, bez nadmiarowych warstw abstrakcji;
- brakowało standardów sieciowych, więc sensowna komunikacja między komputerami praktycznie nie istniała;
- zespół programistów był niewielki, a zmiany rzadsze – dało się jeszcze ogarnąć całość.
Wiele wielkich organizacji – banki, administracja publiczna, wojsko – budowało w tym modelu całe swoje środowiska IT. Powstawały ogromne programy i bazy danych, często implementujące kompletną logikę biznesową w jednym miejscu. Granice dekompozycji, o ile istniały, były raczej techniczne (różne programy wsadowe) niż domenowe.
Paradoks polega na tym, że te systemy do dziś działają. W wielu krajach jądro rozliczeń bankowych, systemy emerytalne czy rejestry obywateli nadal opierają się na mainframe’owych monolitach. Ich utrzymanie jest trudne, ale jednocześnie – przetestowane przez dekady i bardzo stabilne.
Terminale znakowe jako pierwowzór cienkiego klienta
Kolejnym krokiem, który zaczął przypominać nowoczesną dekompozycję, było wprowadzenie terminali znakowych. Zamiast kart perforowanych użytkownicy dostali urządzenia z klawiaturą i ekranem, podłączone kablami do mainframe’a. Terminale nie posiadały prawie żadnej logiki – pełniły rolę „okna” do centralnego systemu.
Powstał pierwszy wyraźny podział:
- świat użytkownika – terminal, prosty interfejs tekstowy, wprowadzanie i wyświetlanie danych,
- świat systemu – mainframe, w którym działo się wszystko: logika biznesowa, walidacje, operacje na bazie danych.
Ten model, choć sprzętowo prymitywny, bardzo przypomina dzisiejszego cienkiego klienta. Użytkownik pracuje na urządzeniu końcowym, a cała „inteligencja” mieszka w centrum danych. Dekompozycja polega tu przede wszystkim na rozdzieleniu prezentacji (terminal) od przetwarzania (host). To wciąż jeden system, ale z jedną, prostą granicą.
Centralizacja miała liczne zalety: łatwiejsze zarządzanie bezpieczeństwem, uproszczone kopie zapasowe, kontrola nad wersją oprogramowania. Z drugiej strony każda zmiana wymagała pracy w tym samym, dużym monolicie, co przy rosnącej liczbie funkcji stawało się coraz większym wyzwaniem.
Dziedzictwo mainframe’ów, które wciąż nas dogania
Choć świat poszedł naprzód, wiele myśli z epoki mainframe’ów wraca dziś w zaskakujący sposób. Przykłady:
- centralizacja jako sposób na bezpieczeństwo – podobnie jak kiedyś mainframe był pilnie strzeżonym centrum, dziś w chmurze buduje się centralne konta, huby sieciowe i wspólne usługi bezpieczeństwa;
- „cienki klient” – współczesne aplikacje webowe lub VDI (wirtualne pulpity) to ten sam pomysł w nowej formie: logika i dane po stronie serwera, lekki interfejs po stronie użytkownika;
- dług technologiczny – ogromne monolity mainframe’owe pokazują, jak trudno zmodernizować system, który był budowany jako jeden niepodzielny byt.
Historia mainframe’ów uczy też pokory: wiele z tego, co wyglądało na „koniec historii” architektury, po latach okazało się tylko jednym z etapów. Tak samo będzie zapewne z dzisiejszymi mikroserwisami.

Minikomputery i narodziny myślenia o modułowości
Od jednego „boga” do wielu mniejszych węzłów
W latach 70. i 80. zaczęła się era minikomputerów, takich jak PDP czy VAX. Były one wciąż duże w porównaniu z PC, ale znacznie tańsze i bardziej dostępne niż mainframe’y. Firmy zaczęły kupować po kilka, kilkanaście maszyn do różnych działów: księgowości, logistyki, produkcji.
To był pierwszy poważny krok w kierunku systemów rozproszonych – choć w bardzo pierwotnej formie. Zamiast jednego „boga” mainframe’a pojawiło się wiele mniejszych węzłów, z których każdy realizował fragment funkcji organizacji. W praktyce często wyglądało to tak, że:
- dział księgowości miał swój system finansowo-księgowy na jednym minikomputerze,
- magazyn pracował na oddzielnym systemie gospodarki magazynowej,
- produkcja używała jeszcze innego rozwiązania, często od innego dostawcy.
Dane zaczęły się rozjeżdżać, a integracja między tymi światami była ręczna: wydruki, dyskietki, czasem prymitywne połączenia sieciowe. Mimo to był to ważny krok: pojawiła się realna potrzeba, żeby różne systemy potrafiły ze sobą rozmawiać.
Pierwsze zdecentralizowane sieci i łączenie maszyn
Wraz z minikomputerami rozwijały się pierwsze sieci lokalne. Łączono maszyny kablami, powstawały proste protokoły komunikacji. Na horyzoncie zaczęła się rysować wizja organizacji, w której:
- każdy dział ma swój system,
- między systemami krąży informacja – zamówienia, stany magazynowe, faktury,
- część obliczeń może być wykonywana lokalnie, a część centralnie.
W architekturze pojawiło się nowe wyzwanie: jak podzielić zakres odpowiedzialności między te systemy? W praktyce granice wynikały często z tego, kto kupił jaki system i do czego. Mało kto świadomie projektował całą architekturę IT organizacji jako spójną całość – dominował pragmatyzm i lokalne optymalizacje.
Ten etap jest ciekawy z jednego powodu: bardzo przypomina dzisiejsze problemy przy migracji do mikroserwisów czy chmury. Każdy zespół/dział buduje „swoje”, a potem ktoś musi to wszystko połączyć w sensowny ekosystem.
Moduły, biblioteki i dekompozycja w kodzie
Na poziomie oprogramowania minikomputery przyniosły też inny ważny trend: modułowość w kodzie. Programiści zaczęli intensywniej korzystać z:
- podprogramów i procedur (subroutines),
- modułów i bibliotek współdzielonych przez różne aplikacje,
- coraz wyraźniejszego podziału na warstwy: np. warstwa dostępu do danych vs. logika biznesowa.
Nadal mówimy tu o jednym systemie w sensie wdrożenia – aplikacja księgowa była budowana i instalowana jako całość. Jednak jej wewnętrzna struktura stawała się coraz bardziej złożona i uporządkowana. Dekompozycja przesunęła się z poziomu sprzętowego (wiele minikomputerów) na poziom kodu i modułów.
Dla wielu organizacji był to też moment, gdy struktura firmy zaczęła odwzorowywać się w strukturze systemów. Osobne działy zamawiały, rozwijały i utrzymywały osobne aplikacje. Ten mechanizm, później opisany jako Prawo Conwaya, działał już wtedy – tylko nikt go jeszcze formalnie nie nazwał.
Prawo Conwaya w zarodku – firmy rysują swoje systemy
Rozproszone systemy w skali organizacji
Gdy minikomputery rozgościły się w firmach, nagle okazało się, że „system” to już nie jedna maszyna, ale cała sieć powiązanych (albo i nie) rozwiązań. Zarząd mógł pierwszy raz zadać niewygodne pytanie: „Dlaczego stan magazynu w systemie produkcji nie zgadza się z tym w systemie sprzedaży?”.
Odpowiedź była brutalnie prosta: bo każdy system żył własnym życiem. Dane były powielane, aktualizowane w różnym rytmie, a synchronizacja odbywała się przez:
- wydruki z jednego systemu przepisywane do drugiego,
- eksporty na taśmach czy dyskietkach,
- ad-hoc skrypty, które ktoś kiedyś napisał i „jakoś działają”.
To właśnie wtedy powstało intuicyjne rozumienie, że granice systemów powinny pokrywać się z granicami odpowiedzialności biznesowej: księgowość odpowiada za finanse, magazyn za stany, produkcja za zlecenia. Niewiele miało to jeszcze wspólnego z dzisiejszym DDD, ale kierunek był podobny – systemy zaczęły odzwierciedlać strukturę organizacji, a nie tylko możliwości sprzętu.
Standardy komunikacji – pierwsze kroki do „kontraktów” między systemami
Większa liczba maszyn oznaczała więcej połączeń. Chaos protokołów i formatów wymusił pierwsze próby normalizacji komunikacji. Pojawiły się pomysły typu:
- zdefiniowane formaty plików wymiany (np. konkretny układ pól w pliku z fakturami),
- proste interfejsy API oparte na komunikatach w sieci lokalnej,
- wspólne „słowniki danych” dla całej organizacji.
Brzmi znajomo? To wczesna wersja tego, co dziś nazywamy kontraktami między usługami. Nie było jeszcze REST-a ani gRPC, ale pojawiło się rozumienie, że dwa systemy muszą się umówić nie tylko jak rozmawiają (protokół), lecz także o czym rozmawiają (model danych).
W wielu firmach pierwsze projekty integracyjne kończyły się powstaniem nieformalnych „hubów” – jednego systemu, który stawał się centrum wymiany danych. To był zalążek tego, co później przybrało formę EDI, ESB, a wreszcie nowoczesnych platform integracyjnych.
Rewolucja PC i architektura klient–serwer
Komputer na biurku – nowy rodzaj mocy obliczeniowej
Pojawienie się komputerów osobistych (PC) wprowadziło zupełnie nowy element do układanki: moc obliczeniowa trafiła na biurka pracowników. Nagle użytkownik nie musiał już być tylko „terminalem” do centralnego systemu. Mógł na swoim komputerze:
- tworzyć i edytować dane,
- przetwarzać je lokalnie (arkusze kalkulacyjne, makra, pierwsze lokalne aplikacje),
- przechowywać własne „mikrosystemy” – często w plikach Excela czy Accessa.
Na początku wiele organizacji traktowało PC jako luksusowe maszyny do edycji tekstu i arkuszy. Jednak szybko okazało się, że logika biznesowa zaczyna wyciekać z centralnych systemów na obrzeża. Pracownicy tworzyli własne raporty, wyliczenia, a nawet mini-aplikacje, które podejmowały za nich decyzje. To była dekompozycja w najczystszej postaci – tyle że dzika, niekontrolowana.
Od grubego klienta do pierwszego klient–serwer
Naturalnym kolejnym krokiem stało się przenoszenie części „prawdziwego” oprogramowania na PC. Pojawiły się grube klienty – bogate aplikacje desktopowe instalowane na stacjach roboczych, które:
- prezentowały dane w bardziej przyjazny sposób,
- wykonywały sporą część logiki biznesowej lokalnie,
- komunikowały się z centralną bazą danych przez sieć.
Tak narodziła się klasyczna architektura klient–serwer. Serwer (zwykle baza danych) odpowiadał za trwałe przechowywanie informacji i część logiki (procedury składowane), a klient – za interfejs i pozostałe zasady działania. Dekompozycja była już dwuwymiarowa:
- technicznie: podział na klienta i serwer,
- funkcjonalnie: osobne moduły aplikacji odpowiadające za różne obszary (sprzedaż, magazyn, raportowanie).
Był to ogromny skok jakościowy dla użytkowników – interfejsy graficzne, okienka, myszka. Z perspektywy architekta pojawił się jednak nowy problem: jak utrzymać spójność logiki biznesowej rozlanej po tysiącach stacji roboczych?
Klient–serwer jako pierwszy masowy „rozpad” monolitu
Dla wielu organizacji przejście z terminali znakowych na grube klienty oznaczało, że monolit pękł na dwie duże części:
- warstwa serwerowa – często nadal monolityczna baza danych i zestaw procedur,
- warstwa kliencka – rozbudowane aplikacje, czasem różniące się wersją między działami.
Typowy scenariusz wyglądał tak: główny system ERP lub finansowy nadal żył na serwerze, ale poszczególne działy dostawały „swoje” moduły klienckie. Jeden moduł do fakturowania, inny do kadr, jeszcze inny do planowania produkcji. Logika biznesowa była dzielona pół na pół: część zasad w bazie, część w kliencie.
To rozdzielenie przypomina dzisiejsze spory o to, ile logiki powinno być w mikroserwisie, a ile w „frontendzie”. Wtedy też ścierały się dwa podejścia:
- „mądry serwer, głupi klient” – maksymalnie dużo logiki w bazie i procedurach, klient głównie wyświetla dane,
- „bogaty klient” – serwer głównie trzyma dane, a prawdziwe życie dzieje się w aplikacji na PC.
W praktyce kończyło się to hybrydą, którą trudno było zrozumieć nowym członkom zespołu. Część walidacji była w procedurach składowanych, część w kodzie aplikacji, a część… w instrukcji dla użytkownika.
Rozmnażanie się aplikacji – niewidzialne mikroserwisy na biurkach
PC w organizacjach miały jeszcze jedną konsekwencję: eksplozję liczby małych, lokalnych systemów. Administratorzy widzieli duże aplikacje klient–serwer, ale prawdziwa dekompozycja odbywała się w cieniu:
- arkusze kalkulacyjne wyliczające premie,
- lokalne bazy Access robiące za mini-CRM,
- skrypty w FoxPro, Clipperze czy Paradoxsie pisane przez zaawansowanych użytkowników.
Każdy taki plik był w pewnym sensie mikroserwisem: realizował wąską funkcję, był utrzymywany przez jedną osobę, często miał własny „model danych”. Problem pojawiał się, gdy twórca odchodził z firmy, a nikt nie wiedział, jak działa jego „magiczny arkusz”.
To doświadczenie do dziś wpływa na nieufność części menedżerów wobec nadmiernej decentralizacji. Gdy słyszą „mikroserwisy zarządzane przez niezależne zespoły”, mają przed oczami nie nowoczesne CI/CD, tylko setki nieudokumentowanych plików Excela z lat 90..
Synchronizacja i konflikty – pierwsze bóle rozproszenia
Architektura klient–serwer ujawniła też klasyczny problem systemów rozproszonych: spójność danych. Jeśli wiele grubych klientów jednocześnie modyfikowało dane w centralnej bazie, trzeba było rozwiązać szereg kwestii:
- blokady rekordów,
- konflikty przy jednoczesnej edycji,
- transakcje rozciągające się na kilka operacji biznesowych.
W odpowiedzi pojawiały się coraz bardziej wyrafinowane mechanizmy w bazach danych i frameworkach komunikacyjnych. Zaczęto myśleć o transakcjach jako o granicy spójności, a nie o całym systemie jako jednym, absolutnie spójnym bycie. To ważne przesunięcie mentalne – bez niego późniejsze zmagania z eventual consistency w mikroserwisach byłyby znacznie trudniejsze do zaakceptowania.
Prawo Conwaya w wydaniu klient–serwer
Gdy organizacje rosły, ich struktura zaczęła coraz bardziej odbijać się w architekturze klient–serwer:
- osobne zespoły utrzymywały serwery i bazy danych,
- inne zespoły rozwijały aplikacje klienckie,
- jeszcze inne odpowiadały za sieć i stacje robocze.
Efekt? Architektura zaczęła pękać tam, gdzie przebiegały linie podziału organizacyjnego. Zamiast jednego produktu IT pojawiły się „produkty” w rozumieniu wewnętrznych działów: „aplikacja sprzedażowa”, „moduł kadr”, „moduł raportowy”. Te moduły miały swoje cykle wydawnicze, priorytety i backlogi, które rzadko idealnie się zgrywały.
Jeśli dziś mikroserwis A nie może wdrożyć zmiany, bo czeka na zmianę w mikroserwisie B, to jest to współczesna wersja sytuacji, gdy zespół od klienta nie może wypuścić nowej funkcji, bo zespół od bazy nie zdążył dodać kolumny.
Web, trójwarstwowość i pierwsze poważne systemy rozproszone
HTTP jako uniwersalny klej
Pojawienie się Webu było momentem, gdy protokół sieciowy stał się uniwersalnym językiem integracji. Tam, gdzie wcześniej królowały prywatne protokoły i firmowe wynalazki, wszedł HTTP – prosty, tekstowy i wspierany przez wszystkich. Nagle okazało się, że:
- do systemu można dostać się z dowolnej przeglądarki,
- frontend nie wymaga instalacji na stacjach roboczych,
- różne systemy mogą wymieniać dane po tym samym protokole.
To był ogromny impuls do standaryzacji interfejsów. Nawet jeśli na początku „API” oznaczało skrypt CGI przyjmujący dane z formularza, był to pierwsze poważne zbliżenie do dzisiejszego myślenia o usługach sieciowych.
Trójwarstwowość – od klient–serwer do klient–serwer–serwer
Architektura klient–serwer szybko zaczęła pękać w szwach. Grube klienty były trudne w utrzymaniu, a centralne bazy danych stawały się wąskim gardłem. Rozwiązaniem stała się architektura trójwarstwowa:
- warstwa prezentacji – przeglądarka lub cienki klient,
- warstwa logiki biznesowej – serwer aplikacji (J2EE, .NET, itp.),
- warstwa danych – baza danych.
To przesunięcie miało ogromne znaczenie dla dekompozycji. Logika biznesowa została wyciągnięta z bazy danych i stacji roboczych do dedykowanej warstwy. Dzięki temu można było:
- centralnie zarządzać regułami biznesowymi,
- skalować warstwę aplikacji poziomo (więcej serwerów),
- zastępować interfejs użytkownika bez zmiany całej logiki.
W praktyce wiele firm przeżyło wtedy swoją pierwszą „mini-migrację do mikroserwisów”: trzeba było wyrwać reguły z procedur składowanych i przenieść je do kodu aplikacji. Brzmi znajomo dla tych, którzy dziś przenoszą logikę z monolitów do usług?
Serwery aplikacyjne i początki usług
Serwery aplikacyjne – od JBossów, WebLogiców, WebSphere’ów po .NET – wprowadziły pojęcie komponentów, które można było wdrażać, konfigurować i współdzielić. EJB, COM+, CORBA – wszystkie te technologie próbowały odpowiedzieć na jedno pytanie: jak zorganizować dużą aplikację w zestaw współpracujących elementów?
Chociaż wiele z tych rozwiązań bywało ciężkie i skomplikowane, przyniosły kilka istotnych idei:
- wyraźne interfejsy między komponentami,
- deklaratywne zarządzanie transakcjami i bezpieczeństwem,
- możliwość zdalnego wywoływania metod (RMI, DCOM, CORBA).
Był to krok w stronę tego, co później nazwano SOA – Service-Oriented Architecture. Zamiast pojedynczych modułów w kodzie zaczęto mówić o usługach, które świadczą określone funkcje dla reszty organizacji. Wiele wczesnych implementacji SOA kończyło jako „gruby ESB w środku i spaghetti wokół”, ale zmiana optyki – myślenie w kategoriach usług – została.
Webowe aplikacje biznesowe – cienki klient na serio
Gdy przeglądarki dojrzały, organizacje zaczęły masowo przenosić aplikacje biznesowe do Webu. Terminal znakowy z czasów mainframe’a odrodził się w nowej formie: cienki klient HTTP. Tym razem jednak:
- interfejs był bogatszy (HTML, JavaScript, CSS),
- komunikacja szła po zunifikowanej sieci (TCP/IP, HTTP),
- serwer aplikacji mógł obsłużyć tysiące użytkowników równocześnie.
Asynchroniczność, AJAX i pierwsze „pseudo-mikroserwisy”
Przez długi czas Web był w gruncie rzeczy powolnym terminalem: żądanie, odpowiedź, przeładowanie strony. Pojawienie się AJAX zmieniło tę dynamikę. Przeglądarka przestała być tylko silnikiem do renderowania HTML – stała się pełnoprawnym uczestnikiem rozmowy z serwerem.
Nagłe ożywienie interfejsów przyniosło ciekawy efekt uboczny. Zaczęły się pojawiać małe, wyspecjalizowane endpointy HTTP, które nie generowały całych stron, tylko zwracały fragment danych w JSON lub XML. Niby ciągle był jeden monolit na serwerze, ale z zewnątrz zaczynał wyglądać jak zbiór małych usług:
- osobny endpoint do podpowiadania nazw klientów,
- inny do liczenia dostępności towaru,
- jeszcze inny do walidacji numeru NIP w tle.
Programiści frontendu zaczęli myśleć o funkcjonalnościach jak o remote funkcjach, a nie tylko o widokach. Powstawały pierwsze nieformalne kontrakty: „to API zwraca takie pola, w takim formacie”. Kto kiedyś zmieniał nazwę pola w JSON-ie, po czym zobaczył rozsypany JavaScript na trzech ekranach, ten wie, jak rodziła się świadomość wersjonowania i kompatybilności wstecznej.
REST, SOAP i spór o to, czym właściwie jest usługa
Kiedy HTTP zadomowiło się już na dobre, zaczęła się dyskusja: skoro wszyscy i tak gadają po HTTP, to w jaki sposób opisywać i organizować te „rozmowy”? Odpowiedzią pierwszej fali była SOA oparta na SOAP i WSDL. Usługa miała ściśle zdefiniowany kontrakt, format wiadomości, typy danych. Dla wielu organizacji brzmiało to jak spełnienie marzeń: wreszcie wszystko „enterprise”, opisane i wygenerowane z narzędzi.
W praktyce często kończyło się na ogromnych, centralnych ESB (Enterprise Service Bus), które miały być mózgiem integracji, a stawały się wąskim gardłem. Każda nowa usługa musiała przejść przez zespół integracji, dopasować się do schematu, przejść akceptację. Architektura była rozproszona technicznie, ale procesowo – bardzo scentralizowana.
Równolegle wyrastał inny nurt – REST w luźniejszym, praktycznym wydaniu. Zamiast rozbudowanych kontraktów SOAP, po prostu:
- używano HTTP tak, jak zaprojektowano (GET, POST, PUT, DELETE),
- adresowano zasoby za pomocą URL-i,
- zwracano lekkie formaty (najpierw XML, potem głównie JSON).
To była kolejna zmiana optyki: zaczęto myśleć o systemach jako o sieci zasobów i usług, do których można dotrzeć z dowolnego miejsca. Kiedy pierwszy raz jakiś zespół z innego działu zużył „twoje” API, zamiast się do ciebie wpiąć na poziomie bazy, poczułeś, że granica systemu przesunęła się ku interfejsowi sieciowemu.
Skalowanie poziome i pierwsze zderzenie z granicami monolitu
Rosnący ruch webowy wymusił nowe podejście do skalowania. Już nie wystarczało kupić większy serwer. Trzeba było zacząć skalować poziomo: więcej instancji tej samej aplikacji, load balancer z przodu, rozdzielanie ruchu.
To generowało bardzo konkretne problemy, które później wrócą przy mikroserwisach:
- sesja użytkownika – czy trzymać ją w pamięci jednego serwera, czy zewnętrznie (np. w cache rozproszonym)?,
- pliki – gdzie zapisywać uploady, jeśli jutro instancja zostanie wyłączona?,
- zadania w tle – który serwer ma je wykonywać, żeby nie robić tego podwójnie?
Nagłe odkrycie, że „dwa takie same serwery to nie to samo, co jeden dwa razy mocniejszy”, kazało uporządkować pojęcia stanu, idempotencji, powtarzalności operacji. Wiele zespołów pierwszy raz zrozumiało, że aplikacja to nie tylko kod, ale i kontrakty dotyczące tego, jak ten kod zachowuje się w środowisku rozproszonym.
Cache, CDN i dzielenie świata na „blisko” i „daleko”
Kiedy ruch wystrzelił, a użytkownicy pojawili się na różnych kontynentach, odkryto inną formę dekompozycji: podział według odległości. To, co najczęściej czytane i rzadko zmieniane, zaczęło być wypychane do CDN-ów, bliżej użytkowników.
Oznaczało to, że jedna część systemu – statyczne zasoby, obrazy, skrypty – żyła w rozproszonych magazynach na całym świecie, a inna – API i logika – wciąż siedziała w kilku data center. To uczyło, że:
- nie wszystko musi być tu i teraz w jednym miejscu,
- część funkcji lepiej „zepchnąć” jak najbliżej użytkownika,
- spójność nie zawsze jest globalna – ważniejsze bywa lokalne wrażenie szybkości.
To myślenie wróci później w modelach edge computing czy w micro frontends, ale korzenie są właśnie tutaj: rozdzieleniu tego, co główne i dynamiczne, od tego, co poboczne, ale ważne dla odbioru jakości.
SOA w wydaniu korporacyjnym – usługi na papierze i w rzeczywistości
Gdy pojęcie usług się upowszechniło, wiele dużych organizacji ogłosiło, że „przechodzi na SOA”. Powstawały katalogi usług, rejestry UDDI, dokumentacje opisujące, że dział finansów oferuje takie a takie usługi płatnicze, a dział HR takie a takie usługi kadrowe.
Na poziomie diagramów wyglądało to imponująco: prostokąty, strzałki, opisane SLA. Na poziomie kodu często okazywało się, że:
- „usługa” to wciąż jedna wielka aplikacja na serwerze aplikacyjnym,
- interfejsy są zaprojektowane bardziej pod potrzeby konkretnego klienta niż jako uniwersalne API,
- zmiana drobnego pola w jednym systemie wymaga koordynacji pięciu działów i trzech vendorów.
To starcie ideału z praktyką zostawiło ważną lekcję: sam podział na usługi na poziomie dokumentacji nie wystarczy. Potrzebne są także niezależne cykle życia, realna autonomia zespołów i możliwość wdrażania zmian w jednym miejscu bez zatrzęsienia w całej organizacji. Brzmi jak preludium do mikroserwisów? Bo tym właśnie było.
Organizacja kontra architektura – druga odsłona prawa Conwaya
Wraz z SOA zmienił się też sposób organizacji pracy. W wielu firmach pojawiły się osobne zespoły „od usług” i osobne „od aplikacji”. Efekt bywał paradoksalny: aplikacje potrzebowały zmian szybciej niż zespoły od usług były w stanie je dostarczyć.
Znowu zwyciężały granice organizacyjne:
- dział A miał swoje priorytety i budżet,
- dział B swoje,
- system końcowy musiał jakoś funkcjonować pomiędzy nimi.
Programiści radzili sobie po swojemu: jeśli oficjalna usługa nie nadążała, powstawała nieoficjalna – czasem jako dodatkowy endpoint, czasem jako osobny serwis. To były pierwsze „dzikie mikroserwisy”, tworzone oddolnie, by ominąć biurokrację. Formalnie wszystko było dalej jednym wielkim systemem SOA, ale de facto w organizmie zaczęły pojawiać się małe, samodzielne organy.
Licencje, monolity vendorów i motyw ekonomiczny dekompozycji
Jest jeszcze wątek, o którym mało się mówi w podręcznikach, a który w praktyce mocno wpływał na architekturę: model licencjonowania. Wielkie aplikacje ERP, CRM czy systemy billingowe były zazwyczaj sprzedawane jako duże monolity. Każdy dodatkowy moduł kosztował, a integracja bywała limitowana zapisami w umowach.
Zespoły IT szukały więc sposobów na oderwanie części funkcji od centralnych molochów. Zamiast kupować kolejny moduł, tworzyły własną usługę, która:
- czytała dane z monolitu (raportowo),
- realizowała dodatkową logikę,
- zapisywała wyniki z powrotem lub trzymała je w osobnej bazie.
Tak powstawały systemy satelitarne. Formalnie były „dodatkami”, ale architektonicznie zaczynały żyć własnym życiem. Dla deweloperów był to trening w wycinaniu wąskich fragmentów funkcjonalności i opakowywaniu ich w niezależne aplikacje – dokładnie to, czego później wymagają mikroserwisy.
Testowanie i jakość w rozproszonym świecie
Wraz z rozproszoną architekturą zmieniła się też skala problemów z testowaniem. W czasach jednego monolitu wystarczyło mieć dobre środowisko testowe, bazę z danymi i zestaw scenariuszy end-to-end. Gdy do gry weszły:
- wiele aplikacji webowych,
- kilka systemów backendowych,
- szereg usług SOA/REST integrujących się między sobą,
okazało się, że odtworzenie prawdziwego środowiska jest trudne, czasem wręcz nierealne. Pojawiły się pierwsze poważne:
- test doubles dla usług – stuby, mocki, symulatory API,
- testy kontraktowe – sprawdzające, czy klient i serwer rozumieją się co do formatu danych,
- automatyzacja środowisk – skrypty budujące całe zestawy aplikacji w spójnym stanie.
Było to preludium do późniejszych praktyk DevOps i Infrastructure as Code. Kiedy masz pięć usług i trzy aplikacje, da się to jeszcze złożyć ręcznie. Gdy robi się ich kilkadziesiąt – pozostaje automatyzacja i standaryzacja. A to z kolei wymusza myślenie o systemie jako o kolekcji wymiennych elementów, nie jednym wielkim bycie.
Od trójwarstwowości do „n-warstwowości” – logiczne a fizyczne granice
Na diagramach architektonicznych przez długi czas królowała trójwarstwowość: prezentacja, logika, dane. Gdy jednak systemy rosły, w praktyce zaczęto dostrzegać więcej warstw i rodzajów granic:
- oddzielne warstwy integracyjne – serwisy, które istnieją tylko po to, by spiąć dwa inne systemy,
- warstwy raportowe – hurtownie danych, BI, analityka,
- warstwy bezpieczeństwa – proxy, bramy, systemy autoryzacji.
To naturalne „rozrastanie się” trzech warstw w coś bardziej złożonego obnażyło pewien fakt: granice logiczne nie muszą pokrywać się z granicami fizycznymi. Moduł logiczny może być rozłożony na kilka procesów, a pojedyncza maszyna może hostować kilka różnych aplikacji.
To z kolei prowadziło do pytań, które dziś zadaje sobie każdy projektujący mikroserwisy: gdzie postawić granicę? Co razem wdrażać, a co oddzielić? Jak bardzo ściśle powiązane są poszczególne fragmenty logiki? Trójwarstwowość była wygodnym punktem startu, ale praktyka wymusiła subtelniejsze podejście do podziału systemów.
Doświadczenia, które ułatwiły narodziny mikroserwisów
Do momentu, gdy w języku inżynierów IT pojawiło się słowo „mikroserwis”, zdążyło się już zebrać całkiem sporo doświadczeń:
- jak trudno utrzymać jeden ogromny system monolityczny,
- jak bardzo procesy organizacyjne potrafią zablokować architekturę techniczną,
- jak pomocne są wyraźne kontrakty sieciowe i wersjonowanie interfejsów,
- jak kłopotliwe jest globalne testowanie czegoś, co żyje w wielu częściach naraz.
Dlatego, gdy pojawiły się historie firm, które zaczęły rozbijać swoje monolity na dziesiątki małych usług wdrażanych niezależnie, dla wielu osób nie brzmiało to jak rewolucja, tylko jak konsekwentne dokończenie drogi, którą szli od lat. Zamiast jednego wielkiego ESB – lekkie kolejki. Zamiast centralnego katalogu usług – autonomiczne zespoły z własnymi API. Zamiast jednej ogromnej bazy – dane podzielone według kontekstów biznesowych.
Innymi słowy: zanim na prezentacjach pojawiły się modne diagramy z dziesiątkami serwisów w chmurze, świat IT zdążył przećwiczyć większość problemów, które dziś nazywa się „wyzwaniami mikroserwisów”. Zrobił to na mainframe’ach, minikomputerach, w PC-tach pod biurkami i w grubych klientach. Dlatego historia dekompozycji nie zaczyna się na Kubernetesie – ona tam tylko nabiera nowego tempa.
Najczęściej zadawane pytania (FAQ)
Na czym polega dekompozycja systemów IT?
Dekompozycja systemów IT to świadomy podział dużego, złożonego systemu na mniejsze, bardziej zrozumiałe elementy. Chodzi o to, aby zamiast jednego „wielkiego potwora” mieć zestaw części, które da się osobno rozwijać, testować i utrzymywać.
Te części mogą być definiowane na różne sposoby: jako moduły w monolicie, oddzielne aplikacje, serwisy, aż po mikroserwisy. Zawsze jednak chodzi o ten sam cel – ograniczyć złożoność, zminimalizować ryzyko każdej zmiany i umożliwić zespołom pracę bez wchodzenia sobie w drogę na każdym kroku.
Dlaczego w czasach mainframe’ów dominowały monolity?
Monolity w erze mainframe’ów były naturalną konsekwencją ówczesnych ograniczeń. Sprzęt był kosmicznie drogi, pamięć śmiesznie mała, a standardów sieciowych praktycznie nie było. Duplikowanie funkcji na kilku maszynach nie miało sensu ani ekonomicznego, ani technicznego.
Dlatego organizacje budowały jeden centralny system, często w jednym języku (np. COBOL), na jednym mainframie. Logika biznesowa i dane lądowały w jednym, ogromnym środowisku. Paradoks polega na tym, że wiele z tych „dinozaurów” działa do dziś – w bankowości, administracji czy systemach emerytalnych – bo są stabilne i przetestowane przez dekady.
Jak wyglądała dekompozycja systemów zanim pojawiły się mikroserwisy?
Zanim ktokolwiek usłyszał o mikroserwisach, dekompozycja odbywała się innymi narzędziami. Najpierw poprzez rozdział na programy wsadowe i moduły w jednym mainframie, potem poprzez oddzielne aplikacje na minikomputerach w działach, dalej – przez architekturę klient–serwer, trójwarstwowe aplikacje webowe i wreszcie SOA z usługami biznesowymi.
Zmieniały się etykietki i technologie, ale motyw pozostawał ten sam: rozdzielić odpowiedzialności, znaleźć sensowne granice (technologiczne, warstwowe, domenowe) i jakoś zapanować nad rosnącą liczbą funkcji, tabel i integracji. Dzisiejsze mikroserwisy są kolejnym etapem tego samego procesu, a nie „odkryciem” dekompozycji.
Jaka jest różnica między architekturą monolityczną a mikroserwisami?
Monolit to jeden duży system, w którym większość funkcji działa w jednym procesie, zwykle w jednej bazie danych. Zmiana w jednym miejscu może niechcący uderzyć w inną część, bo wszystko jest ze sobą mocno sklejone. Łatwiej go uruchomić jako całość, ale trudniej rozwijać, gdy rośnie przez lata.
Mikroserwisy dzielą system na małe, niezależnie wdrażalne serwisy, zwykle skupione wokół konkretnych domen biznesowych (np. płatności, magazyn, klienci). Każdy serwis ma swoją odpowiedzialność, często własną bazę danych i zespół. Zyskujemy elastyczność i skalowanie „po kawałku”, ale płacimy cenę w postaci złożonej komunikacji, monitoringu i koordynacji.
Jakie były główne etapy przechodzenia od mainframe’ów do mikroserwisów?
Jeśli spojrzeć z lotu ptaka, można wyróżnić kilka charakterystycznych etapów:
- mainframe – jeden centralny komputer, wsady, terminale znakowe jako cienki klient, monolityczna logika biznesowa,
- minikomputery – tańsze maszyny w działach, pierwsze myślenie modułowe i rozproszenie obliczeń,
- PC i klient–serwer – aplikacje na biurkach, sieci LAN, podział na część „na kliencie” i „na serwerze”,
- web i trójwarstwowość – przeglądarka jako uniwersalny klient, serwer aplikacji, baza danych,
- SOA i ESB – usługi biznesowe, integracja przez centralny bus, próba uporządkowania wielu systemów,
- chmura i mikroserwisy – małe, autonomiczne serwisy, automatyzacja, ciągłe wdrażanie i skalowanie.
W tle widać nieustanne przesuwanie granic: od „wszystko w jednym pudełku” do „wiele mniejszych klocków, które muszą się dogadać”.
Dlaczego granice systemu częściej wyznacza dziś domena biznesowa niż technologia?
Kiedyś system dzieliło się głównie według warstw i technologii: tu moduł bazy danych, tam warstwa prezentacji, gdzie indziej logika. Dziś coraz częściej ważniejsze jest pytanie: jaka część biznesu za co odpowiada? Stąd nacisk na dekompozycję domenową – serwisy skupione wokół konkretnych obszarów biznesu, a nie tylko „kontrolerów” czy „DAO”.
Taki podział lepiej odzwierciedla organizację i ułatwia rozwój. Zespół odpowiedzialny za dany fragment biznesu (np. rozliczenia) dostaje serwis lub zestaw serwisów, które obejmuje „głową i odpowiedzialnością”. To zmniejsza liczbę zależności między zespołami i pozwala im szybciej reagować na zmiany regulacji, produktów czy procesów.
Co z dziedzictwem mainframe’ów – czy te systemy da się w ogóle „podekomponować”?
Systemy mainframe’owe w wielu organizacjach są rdzeniem krytycznych procesów: rozliczeń, rejestrów, świadczeń. Nie da się ich po prostu wyłączyć i napisać od zera, bo biznes nie przestaje działać nawet na godzinę. Dlatego częściej stosuje się podejście stopniowe: „owijanie” monolitu API, wydzielanie wybranych funkcji na zewnątrz, migracje po kawałku.
Przykładowo bank może zostawić rozliczenia na mainframie, ale nową aplikację mobilną oprzeć o mikroserwisy, które komunikują się z „rdzeniem” przez dobrze zdefiniowane interfejsy. Z perspektywy użytkownika widać nowoczesny system, a w środku wciąż pracuje sprawdzony, choć wiekowy, monolit.
Źródła
- Computer: A History of the Information Machine. Westview Press (2013) – Historia komputerów mainframe, minikomputerów i PC
- Architecture of a Database System. Foundations and Trends in Databases (2007) – Przegląd architektur systemów, monolity vs systemy rozproszone
- Patterns of Enterprise Application Architecture. Addison-Wesley (2002) – Wzorce architektoniczne: warstwy, podział odpowiedzialności, integracja
- Building Microservices. O’Reilly Media (2015) – Mikroserwisy, dekompozycja domenowa, niezależne wdrażanie serwisów






