TL;DR: Pro většinu PHP projektů, na kterých jsem zatím pracoval, je dobře navržený modulární monolit lepší volba než mikroslužby. Tenhle článek vám dá 5 kritérií, podle kterých se rozhodnout – včetně flowchartu a ADR šablony.
Mikroslužby vs. monolit je v PHP týmech otázka, která se vrací pořád dokola. A většina týmů, které se pro mikroslužby rozhodnou příliš brzo, toho do roka lituje.
Vzorec, který vídám častěji: tým čtyř až šesti vývojářů, e-shop nebo B2B SaaS. Stačí, aby někdo přišel s mikroslužbama, protože to tak dělá Netflix a za rok je z aplikace osm samostatných služeb – katalog, objednávky, fakturace, notifikace, sklad, vyhledávání, reporting, uživatelé. Každá s vlastní databází, vlastní deploy pipeline, vlastní logy. Vývojáři ladí distributed tracing, aby zjistili, proč objednávka občas nevznikne. Mezitím jeden z týmu odejde a místo čtyř lidí jsou tři. Náklady na infrastrukturu vyrostou z jednotek tisíc na desítky tisíc Kč měsíčně (managed Kubernetes – control plane, nody, load balancer, registry, monitoring), čas na release nové funkce z dnů na týdny. Projekt prakticky stojí.
Druhý vzorec, o kterém je slyšet míň (protože je nudný): podobná velikost týmu, podobný typ produktu, rozhodnutí opačné. Modulární monolit v Symfony nebo Laravelu, jeden deploy, jedna databáze, striktní hranice mezi doménami. Tři roky vývoje, deploy každý den, levná infrastruktura. O architektuře se diskutuje na hodinu jednou za půl roku, zbytek času se píší features.
Stejný typ produktu, podobná velikost týmu, fundamentálně odlišné výsledky. Jak se rozhodnout předtím, než investujete rok vývoje do špatné architektury? O to tady jde.
Pojmy: monolit, modulární monolit, SOA, mikroslužby
„Mikroslužby“ se dnes používá pro cokoliv od jedné Lambda funkce po systém o padesáti službách. Než půjdu ke kritériím, ujasním čtyři pojmy:
- Monolit – jedna aplikace, jeden deploy, jedna databáze. Klasický PHP projekt: Apache s mod_php nebo
php artisan serve, jeden repozitář. - Modulární monolit – pořád jeden deploy, ale kód je striktně rozdělen do modulů s jasnými hranicemi (bounded contexts). Moduly spolu komunikují přes definovaná rozhraní, ne přímými voláními do cizí tabulky. V Symfony typicky separátní Bundle pro každou doménu. Detailněji v článku o DDD v Symfony.
- SOA – několik větších služeb sdílejících společnou infrastrukturu (ESB, databázi). Historicky enterprise pattern z éry SOAP. Dnes spíš mezistupeň mezi monolitem a mikroslužbami.
- Mikroslužby – mnoho malých, nezávisle deployovatelných služeb, každá s vlastní databází a vlastní komunikační vrstvou.
Co není mikroslužba: deset služeb čtoucích ze stejné databáze (distribuovaný monolit – monolit s distribučním overheadem navíc, nejhorší ze dvou světů), každá metoda jako vlastní HTTP endpoint (nano-služby, kde deployment overhead, latence i debugging jsou noční můrou), nebo služby, jejichž výpadek strhne celý systém (porušuje základní příslib mikroslužeb – fault isolation).
| Architektonický styl | Deploy | Databáze | Komunikace | Vhodný tým |
|---|---|---|---|---|
| Monolit | Jeden artefakt | Sdílená | Přímé volání | 1-5 vývojářů |
| Modulární monolit | Jeden artefakt | Sdílená (striktní hranice) | Interfaces / eventy uvnitř procesu | 3-15 vývojářů |
| SOA | Několik artefaktů | Částečně sdílená | ESB / API brána | 10-30 vývojářů, enterprise |
| Mikroslužby | Mnoho artefaktů | Každá vlastní | HTTP/gRPC/fronta | 15+ vývojářů, zralý DevOps |
5 rozhodovacích kritérií
Každé z těchto kritérií jsem si ověřil na reálných projektech. Žádné není absolutní – rozhodnutí vždy závisí na kontextu. Ale dohromady tvoří framework, který vám ušetří rok bolesti.
1. Velikost týmu
Mikroslužby předpokládají, že máte dost lidí na ownership každé služby. Conway’s Law říká, že architektura systému kopíruje komunikační strukturu organizace. Pokud máte tříčlenný tým a osm služeb, každý vývojář „vlastní“ víc než dvě služby – a nikdo neví, jak celý systém funguje dohromady.
Monolit volte, když: máte méně než 8 vývojářů. Modulární monolit volte pro 5-15 lidí, kde chcete jasné hranice zodpovědnosti.
Mikroslužby zvažte, když: máte dost lidí na to, aby každou službu vlastnil celý tým (ne jeden vývojář). Spotify model pracuje s „squady“ – přibližně 6-12 lidí na jednu doménu.
Zpět k prvnímu scénáři z úvodu: tři vývojáři, osm mikroslužeb. Matematika prostě nevychází. Tři lidi nestíhají udržovat osm deploy pipeline, osm monitoring konfigurací, osm sad integračních testů. Když na takovém setupu selže deploy jedné služby, ladění typicky stojí hodiny – a často se ukáže, že problém je v zastaralé verzi Docker image, ne v kódu.
2. Provozní zralost a deploy potřeba
Dvě kritéria, která bez sebe nedávají smysl. Nezávislý deploy je hlavní příslib mikroslužeb – ale bez zralé DevOps kultury si tím spíš naložíte operační overhead, než získáte rychlost.
Mikroslužby vyplatí, když různé části systému mají fundamentálně odlišný deploy rytmus. Billing se mění jednou za měsíc, katalog produktů se updateuje třikrát denně. Tehdy nezávislý deploy přináší reálnou hodnotu. Když ale releasujete celý systém jednou týdně, nebo když vaše funkce typicky zasahují víc domén najednou (změna workflow objednávek mění katalog, sklad i notifikace), výhoda nezávislosti se ztratí a stejně koordinujete deploy několika služeb najednou.
I kdyby tato potřeba byla reálná, mikroslužby předpokládají zralé prostředí (a to je vzácné): CI/CD pipeline pro každou službu, centralizované logování (ELK, Datadog, Grafana Loki), distributed tracing (Jaeger, Zipkin), service discovery, rolling deployments a rollback strategii. Bez toho všeho přidá nová architektura zbytečný komplikace, který tým pohltí. Místo psaní features ladíte Kubernetes networking.
Monolit volte, když: releasujete jednou týdně nebo méně, funkce zasahují víc domén najednou, nebo tým nemá dedikovaného SRE/DevOps inženýra.
Mikroslužby zvažte, když: různé domény mají reálně odlišný deploy rytmus a tým má zralou DevOps kulturu, infrastructure-as-code, a vývojáře, kteří rozumí operačnímu modelu. Organizační zralost je prerekvizita, ne věc, kterou se naučíte cestou.
Pozor na záměnu příčiny: pokud se vývojáři přetahují o pořadí merge requestů a deploy se kvůli koordinaci odkládá, řešením obvykle nejsou mikroslužby. Stačí feature flags a striktní mergovaní po malý částech (trunk-based development). Tým se z deploye jednou za dva týdny dostanete na každodenní deploy – beze změny architektury.
3. Konzistence dat
Tohle je technicky nejdůležitější kritérium a zároveň nejčastěji podceňované.
V monolitu máte databázové transakce. BEGIN TRANSACTION, uložíte objednávku, strhnete sklad, pošlete notifikaci, COMMIT. Pokud cokoliv selže, vrátíte vše zpět. ACID garantuje konzistenci.
// V monolitu: atomická operace, jeden transakční kontext
$this->entityManager->beginTransaction();
try {
$order = $this->orderRepository->create($orderData);
$this->inventoryService->decrementStock($order->items); // stejná DB
$this->notificationService->scheduleOrderConfirmation($order); // zápis do fronty
$this->entityManager->flush();
$this->entityManager->commit();
} catch (\Exception $e) {
$this->entityManager->rollback(); // vše se vrátí zpět
throw $e;
}
V mikroslužbách neexistuje distribuovaná transakce – nebo existuje (2PC, saga pattern), ale za cenu celkem velké složitosti. Musíte se rozhodnout: buď eventual consistency (data jsou konzistentní „nakonec“), nebo saga orchestration, která je sama o sobě komplexní stavový stroj.
Saga v praxi vypadá takto: vytvoříte objednávku, pošlete zprávu do Inventory service, čekáte na potvrzení. Inventory selže, takže musíte odeslat kompenzační transakci do Order service, aby objednávku zrušila. Jenže co když Order service mezitím taky selže? A co když zpráva do Inventory nedorazí? Najednou řešíte distribuované stavové automaty a idempotentní klíče místo business logiky.
Monolit volte, když: vaše operace přirozeně zasahují víc entit najednou a potřebujete garance konzistence. Finančnictví, zdravotnictví, e-commerce – zde je ACID requirement, ne nice-to-have.
Mikroslužby zvažte, když: domény jsou přirozeně oddělené a eventual consistency je akceptovatelná. Sociální síť: profil uživatele a feed příspěvků mohou být eventual consistent. Nikdo nezaplatí, když nový follower uvidí váš nový příspěvek o pět sekund později.
4. Fault isolation
Jedna chyba shodí celý systém? Například přestane fungovat placení, když jste nasadili úpravu doporučovacího modulu. To je legitimní důvod přemýšlet o službách (nebo o změně přístupu k testování, záleží na kontextu).
V monolitu jedna nekontrolovaná výjimka nebo memory leak může ohrozit celou aplikaci. V mikroslužbách výpadek jedné služby teoreticky neovlivní ostatní – pokud jsou správně navrženy (circuit breaker, timeout, fallback).
Monolit volte, když: různé části aplikace mají podobnou kritičnost. Pokud padne „Reporting“ modul, není tragédie – stejně padne i „Objednávky“. Izolace nepřináší benefit.
Mikroslužby zvažte, když: máte jasně odlišné úrovně kritičnosti. Placení musí fungovat, i když padne doporučovací engine. Autentizace musí fungovat, i když padne notifikační služba. Fault isolation pak přináší reálnou hodnotu – a stojí za komplexnost.
Příklad z Webové Hlídky: monitoring kontrol (HTTP, SSL, SEO) jsem oddělil do workerů komunikujících přes RabbitMQ. Důvod byl přesně fault isolation – pomalé SEO kontroly nesmí blokovat rychlé HTTP status kontroly. Ale neudělal jsem z každého typu workera mikroslužbu. To by byl overkill. Jsou to workery komunikující přes frontu, ale sdílí kód a databázi s monolitem. O tomhle rozhodnutí jsem psal detailněji v článku o architektuře Webové Hlídky.
5. Diverzita technologií
„Potřebujeme Python pro ML část a Go pro high-performance API“ – to je legitimní argument pro mikroslužby. Ale upřímně, jak často ho reálně potřebujete?
Monolit volte, když: celý systém může rozumně žít v PHP. PHP 8.x je dnes rychlý, FrankenPHP umí long-running processes, a async workery vyřešíte přes RabbitMQ. Pro drtivou většinu webových aplikací PHP stačí.
Mikroslužby zvažte, když: máte skutečné performance nebo ecosystem požadavky, které PHP nesplní. Realtime WebSocket server? Go nebo Node.js mají smysl. ML inference? Python s FastAPI. Ale tohle jsou doplňky, ne důvod přepisovat celý systém.
Pozor: viděl jsem týmy, které „potřebovaly“ Node.js mikroslužbu – protože jeden vývojář ho uměl a chtěl ho zkusit. To není architektonický důvod. To je kariérní rozvoj zamaskovaný jako technická nutnost.
Rozhodovací flowchart
Tady je flowchart, který jsem si sestavil pro klienty:
flowchart TD
A[Nový projekt nebo refaktoring?] --> B{Tým < 8 lidí?}
B -->|Ano| C{Regulatorní izolace\nnutná?}
C -->|Ne| D[**Monolit**\nNejjednodušší správná volba]
C -->|Ano| E[**Modulární monolit**\ns izolovaným modulem\npro regulovanou doménu]
B -->|Ne, tým 8-20| F{Zralý DevOps?\nCI/CD, monitoring, tracing?}
F -->|Ne| G[**Modulární monolit**\nNejprve organizační zralost]
F -->|Ano| H{Konzistence dat\nnebo transakce\nnapříč doménami?}
H -->|Ano, kritická| I[**Modulární monolit**\ns CQRS pro čtení]
H -->|Eventual consistency OK| J{Nezávislý deploy\nreálná potřeba?}
J -->|Ne| K[**SOA**\nněkolika větších služeb]
J -->|Ano| L[**Mikroslužby**\nale začněte jednou nebo dvěma]
B -->|Ne, tým 20+| M{Různé škálovací\npožadavky?}
M -->|Ne| G
M -->|Ano| L
Výstup flowchartu jsou čtyři kvadranty:
- Monolit – malý tým, nízká komplexnost, rychlý start
- Modulární monolit – rostoucí tým, bounded contexts, zachovaná jednoduchost deploymentu
- SOA – větší organizace, integrační potřeby, ale bez plného mikroslužbového overheadu
- Mikroslužby – zralá organizace, reálný benefit z nezávislého deploye, zvládnutý operační model
Většina PHP projektů skončí v kvadrantu 1 nebo 2. A to je v pořádku.
Tabulka pro rychlou orientaci – bez flowchartu, pro technické lídry, kteří chtějí okamžitý přehled:
| Signál | Monolit | Modulární monolit | SOA | Mikroslužby |
|---|---|---|---|---|
| Tým | < 5 lidí | 5-15 lidí | 10-30 lidí | 15+ lidí |
| Četnost Deploye | Týdně nebo méně | Denně | Denně, oddělené domény | Vícekrát denně, nezávisle |
| Konzistence dat | Kritická (ACID) | Kritická (ACID) | Částečně sdílená | Eventual OK |
| DevOps zralost | Žádná | Základní | Střední | Vysoká |
| Regulace | Ne | Izolovaný modul | Separátní prostředí | Separátní prostředí |
| Potřeba Fault isolation | Ne | Ne | Částečně | Ano |
Regulatorní výjimka: Bez ohledu na 5 kritérií výše: pokud zpracováváte platební karty (PCI DSS), zdravotní data (HIPAA) nebo osobní data v rozsahu, který vyžaduje audit a omezený přístup (GDPR ve velkém měřítku), izolujte tu doménu – i kdyby ostatní kritéria mluvila pro monolit. „Izolovaný“ tady neznamená jen „jiná tabulka ve stejné databázi“, ale znamená oddělené prostředí, oddělená přístupová práva, oddělený audit log. Buď jako mikroslužba, nebo jako modul s vlastní infrastrukturou.
Případová studie: Webová Hlídka – monolit, který vydržel
Webová Hlídka je můj vlastní projekt – monitoring SaaS pro weby. Jeden PHP monolit, který dělá většinu práce: přijímá requesty, ukládá nastavení kontrol, spravuje uživatele, posílá reporty.
Jenže monitorování samotné – HTTP kontroly, SSL certifikáty, PageSpeed, SEO analýzy – to není synchronní práce. 200 webů × 5 kontrol = 1000 kontrol. Při průměru 3 sekundy na kontrolu je to 50 minut na jedno kolo. Synchronně. To nefunguje.
Rozhodl jsem se nevytrhávat z monolitu celé domény. Místo toho jsem přidal asynchronní vrstvu: RabbitMQ fronty, PHP workery pro rychlé kontroly (HTTP status, SSL), Node.js workery pro kontroly náročné na browser (PageSpeed, SEO). Monolit orchestruje, workery zpracovávají.
Výsledek: monolit zůstal jednoduchý na deploy a debugování. Asynchronní workery jsou izolované – pomalá SEO kontrola neblokuje rychlou HTTP kontrolu. Fault isolation, kde je potřeba; simplicita, kde to jde.
Kdybych v roce jedna přepsal vše na mikroslužby, byl bych rok ladit infrastrukturu místo produktových funkcí. Zbytek monolitu může zůstat, jak je, zatím :)
Obecný princip, který z toho plyne: pokud zvažujete mikroslužby, začněte s jednou. Tou, která má nejjasnější a nejsilnější důvod pro oddělení – fault isolation, regulatorní izolace, technologická diverzita. Jedna služba. Naučte se operační model. Pak se rozhodněte, jestli přidáte druhou. Pragmatický hybrid bývá lepší volba než „čistá“ architektura, která řeší problém, který nemáte.
ADR šablona – Architecture Decision Record
Každé architektonické rozhodnutí by mělo mít písemný záznam. Nejen co jste se rozhodli, ale proč a za jakých okolností byste rozhodnutí přehodnotili.
Bez tohoto záznamu se stane něco předvídatelného: za rok přijde nový vývojář, podívá se na kód a řekne „proč to kurva je takhle?“ A nikdo neví. Původní autoři odešli, Slack zprávy zmizely, wiki je zastaralá. ADR je pojistka proti institucionální amnézii.
ADR (Architecture Decision Record) je jednoduchý dokument, který žije vedle kódu (typicky docs/decisions/). Detailní průvodce ADR šablonou plánuji jako samostatný článek, ale tady je základní struktura:
# ADR-001: Monolit vs. mikroslužby
**Datum:** 2026-05-01
**Status:** Accepted
## Context
[Co je situace, ve které rozhodujeme? Jaká jsou omezení, požadavky, kontext?
Fakta, ne názory. Např.: "Tým má 5 vývojářů. Deploy probíhá jednou týdně.
Zákazníci vyžadují 99.9% uptime. Nemáme DevOps inženýra."]
## Decision
[Co jsme se rozhodli. Konkrétně a jednoznačně.
Např.: "Stavíme modulární monolit v Symfony 7 s oddělením domén
do separátních Bundles. Billing zůstane izolovaný modul s vlastní
infrastrukturou z důvodu compliance."]
## Consequences
[Důsledky rozhodnutí - pozitivní i negativní.
Např.: "+ Jednoduchý deploy, - horizontální scaling bude složitější,
+ tým se nemusí učit Kubernetes."]
## Considered Options
[Co jsme zvažovali a proč jsme to nezvolili.
Stručně, s důvodem. Tabulka alternativ je vhodná.]
## Assumptions
[Na čem rozhodnutí stojí. Pokud se tyto předpoklady změní,
rozhodnutí se musí přehodnotit.
Např.: "Předpokládáme, že tým nepřesáhne 10 vývojářů v horizontu 2 let."]
[Kdy toto rozhodnutí přehodnotíme?
Např.: "Pokud tým přesáhne 12 vývojářů, nebo pokud deploy
jedné domény opakovaně blokuje deploy jiné domény."]
Pět sekcí. Žádná z nich není volitelná – každá dělá jiný druh práce.
Context dokumentuje situaci ve chvíli rozhodnutí. Za rok budete rádi, že víte, jaká byla v té době velikost týmu a jaké byly tlaky.
Decision je jednoznačná. Žádné „zvážíme“ nebo „pravděpodobně“. Rozhodnutí je rozhodnutí.
Consequences jsou upřímné. Architekt, který přiznává jen pozitiva, nepomáhá týmu – připravuje ho o schopnost zvažovat alternativy.
Considered Options ukazuje, že rozhodnutí nebylo náhodné. A brání opakování diskuze za půl roku.
Assumptions jsou klíčové. Většina architektonických rozhodnutí je podmíněná předpoklady – a když se předpoklady změní, rozhodnutí musí být přehodnoceno a dává rozhodnutí expiraci. Architektura není dogma, je to dokument živý jako kód.
ADR nemusí být dlouhý. Stačí jedna A4. Nejdůležitější je, že existuje a žije v repozitáři.
Jedna praktická poznámka k procesu: ADR píšete před implementací, ne po ní. Pokud píšete ADR zpětně, abyste zdokumentovali rozhodnutí, které bylo „samozřejmé“ – to je příznak, že jste rozhodnutí řádně nezvážili. Architektonická rozhodnutí, která se zdají samozřejmá, jsou právě ta, která se za dva roky ukáží jako nejproblematičtější.
Shrnutí
Než se rozhodnete pro monolit nebo mikroslužby v PHP, položte si tři otázky:
- Kolik vás je a jak deployujete? Méně než 8 lidí s týdenním deployem – monolit. Téměř bez debaty (dokážu si představit výjimky, není to dogma nebo nějaká pevná hranice).
- Kde jsou přirozené hranice domén a jaká je kritičnost dat? Pokud transakce přirozeně přesahují domény a data musí být konzistentní, monolit nebo modulární monolit. Pokud domény jsou opravdu samostatné, zvažte oddělení.
- Máte operační zralost? CI/CD, monitoring, tracing, rollback strategie. Pokud ne, mikroslužby komplexnost přidají, neodeberou.
Pro většinu PHP projektů je správná odpověď modulární monolit. Čisté hranice, jednoduchý deploy, žádný operační overhead. Mikroslužby jsou správná odpověď – jen v jiné situaci, než si většina týmů myslí.