Monolit nebo microservices? Záleží na jiných otázkách, než si většina týmů myslí.

Vývoj aplikace se zpomaluje. Každá další změna stojí víc času, dopady se hůř odhadují a orientace v kódu je stále složitější. V takové situaci se často objeví návrh rozdělit systém na microservices.

Na první pohled to zní logicky. Co když ale problém vůbec není v monolitu?

Ve spoustě projektů totiž tým neřeší architekturu, ale technický dluh. Pokud je právě ten skutečnou příčinou zpomalujícího se vývoje, rozdělení systému na více služeb nic nevyřeší. Duplicitní logika, nejasné odpovědnosti i skryté závislosti nezmizí. Jen přibude komunikace mezi službami, složitější provoz a další věci, které bude potřeba řešit.

Jak poznat, kdy microservices řeší skutečný problém a kdy jen přidávají další vrstvu složitosti? Přesně na to se v tomto článku podíváme.

Co microservices skutečně řeší

Microservices dávají smysl ve chvíli, kdy jednotlivé části systému skutečně potřebují fungovat samostatně. Třeba když mají vlastní tempo vývoje, jiné nároky na výkon nebo dostupnost, případně za ně odpovídají oddělené týmy. V takové situaci může být výhodné, aby se jedna část produktu dala měnit, nasazovat nebo škálovat bez přímé koordinace se zbytkem systému.

Pokud ale na produktu pracuje jeden tým, požadavky se stále vyvíjejí a většina změn zasahuje více částí aplikace, bývá monolit praktičtější. Kód, databáze, testy i hlavní business procesy zůstávají pohromadě a změnu lze často provést, ověřit a nasadit jako jeden celek.

Problém nastává, když se microservices použijí jako odpověď na technický dluh nebo zpomalující se vývoj. Nepřehledná logika, duplicity a skryté závislosti tím nezmizí. Tým bude řešit stejné problémy, jen navíc přes API, fronty a více prostředí.

Nejdřív je proto potřeba pojmenovat, co tým skutečně brzdí. Společný deployment? Odlišné nároky na výkon? Potřeba oddělit provozní riziko? Nebo hlavně kód, kterému už nikdo dostatečně nerozumí?

Bez přesné odpovědi jsou microservices spíš změnou formy než řešením.

Cena microservices nezačíná napsáním první služby

Novou službu dnes vytvoříte poměrně rychle. Frameworky, kontejnery, cloudové platformy i AI nástroje výrazně zlevnily samotný vývoj. Drahá část ale začíná až ve chvíli, kdy se služba stane součástí produkčního systému.

Každá služba potřebuje vlastní deployment, konfiguraci, monitoring, logování, alerty, správu prostředí a aktualizace. Jakmile spolu komunikují dvě služby, přibývají timeouty, opakované požadavky, idempotence, verzování API a složitější dohledávání chyb. Už nestačí vědět, že proces selhal. Je potřeba zjistit, ve které službě, v jakém kroku a v jakém stavu zůstala data.

Složitější je i práce s konzistencí. V monolitu často stačí jedna databázová transakce. U více služeb je běžné, že jednotlivé části systému po určitou dobu pracují s rozdílnými daty a některé operace je nutné opakovat nebo kompenzovat.

Nic z toho není neřešitelné. Je ale potřeba počítat s tím, že rozdělením systému vzniká nová provozní režie, kterou tým ponese při každé další změně.

Proto je důležitější jiná otázka než „není už monolit příliš velký?“:

Jaký konkrétní problém bude po rozdělení systému jednodušší než dnes?

Pokud na ni neexistuje jasná odpověď, bývá rozumnější investovat do zjednodušení aplikace než do složitějšího provozu.

Proč je monolit pro jeden produktový tým často praktičtější

Pokud stejný tým navrhuje, vyvíjí i provozuje většinu produktu, samostatné služby mu často nepřinesou skutečnou nezávislost. Lidé stejně potřebují rozumět celému procesu, změny se dotýkají několika částí aplikace a release se koordinuje uvnitř stejné skupiny. Rozdělení systému pak nezmenší množství práce, ale jen ji rozloží mezi více repozitářů, prostředí a způsobů komunikace.

Monolit v takové situaci drží související věci pohromadě. Změnu databáze, business logiky, API i testů lze připravit a nasadit jako jeden celek. Vývojář nemusí nejdřív zjišťovat, která služba vlastní potřebná data, jakou verzi kontraktu používá nebo jestli lokálně spustil všechny závislosti. To zrychluje nejen samotný vývoj, ale také debugging, code review a předávání znalostí v týmu (onboarding).

Výhodou je i možnost systém průběžně upravovat. U produktu, který se stále vyvíjí, se často mění nejen implementace, ale i pochopení samotného problému. Část aplikace, která dnes vypadá jako samostatný celek, může za půl roku úzce souviset s jinou funkcí. Uvnitř monolitu lze takové uspořádání změnit relativně levně. Jakmile jsou stejné části oddělené přes API, fronty a vlastní databáze, každý podobný zásah vyžaduje mnohem více koordinace.

Pro jeden produktový tým tak monolit často není omezením, ale výhodou. Snižuje množství věcí, které je nutné koordinovat, a nechává více času na práci, která skutečně posouvá produkt.

Kdy už microservices dávají skutečný smysl

Říct, že je monolit často lepší volbou, neznamená, že microservices nejsou potřeba. Existuje řada situací, kdy jejich přínosy převáží nad vyšší složitostí i provozními náklady.

Jedním z nejčastějších důvodů je situace, kdy různé části produktu přestávají mít společný životní cyklus. Některé moduly se mění několikrát týdně, jiné zůstávají měsíce beze změny. Pokud každý release vyžaduje koordinaci napříč celou aplikací, může být oddělený deployment přirozeným dalším krokem.

Podobně je tomu u škálování. Pokud jedna část systému zpracovává násobně více požadavků než zbytek aplikace nebo má odlišné požadavky na infrastrukturu, není důvod škálovat celý monolit jen kvůli jednomu modulu.

Samostatná služba může dávat smysl také ve chvíli, kdy konkrétní problém výrazně lépe řeší jiná technologie. Představme si SaaS aplikaci postavenou v Laravelu, která potřebuje zpracovávat video, rozpoznávat řeč nebo provozovat model strojového učení. Místo implementace všeho v PHP může být rozumnější vytvořit samostatnou službu v Pythonu, využít jeho knihovny a Laravel s ní propojit přes API nebo frontu. Důvodem ale není to, že je Python „lepší“. Důvodem je, že pro daný problém nabízí vhodnější ekosystém.

Silným argumentem bývá také organizace vývoje. Jakmile na různých částech produktu dlouhodobě pracují samostatné týmy, začíná být důležité, aby si navzájem co nejméně zasahovaly do práce. Oddělené služby pak mohou snížit množství koordinace i riziko, že změna jednoho týmu ovlivní ostatní.

Společným jmenovatelem všech těchto situací je, že microservices řeší konkrétní problém, který v monolitu začíná být dražší než samotné rozdělení systému.

Velikost codebase ani počet řádků kódu mezi tyto důvody nepatří. Stejně tak jím není technický dluh nebo nepřehledná struktura aplikace. Ty je potřeba řešit bez ohledu na to, jestli systém běží jako monolit nebo jako sada samostatných služeb.

Závěr

Nenechte se strhnout trendy ani tlakem okolí. Architektura není soutěž v počtu služeb ani použitých technologiích. Je to série rozhodnutí, která by měla odpovídat velikosti produktu, zkušenostem týmu i problémům, které skutečně řešíte.

Pokud vám dobře navržený monolit umožňuje produkt rychleji vyvíjet, bezpečněji měnit a jednodušeji provozovat, není důvod ho rozdělovat jen proto, že je to zrovna populární směr.

Microservices jsou výborný nástroj. Stejně jako každý jiný nástroj ale dávají největší smysl ve chvíli, kdy řeší konkrétní problém.