Kdy API, kdy eventy
Debatu „API versus eventy“ jsem zažil snad v každém týmu — a málokdy se vedla dobře. Argumentuje se tím, co je moderní, co už máme nakoupené, nebo jak se to dělalo vždycky. Místo toho používám pár otázek o samotném procesu. Většinou rozhodnou samy; tady je shrnuju i s příklady.
Kdo potřebuje odpověď a kdy
Otázka, která architektura je „lepší“, se rozhodnout nedá. Užitečnější je ptát se, kdo potřebuje odpověď a kdy: když volající bez výsledku nemůže pokračovat, potřebujete synchronní volání; když ho výsledek zajímá „až to bude“, nebo zajímá víc příjemců, jste na území eventů. Většina sporů skončí ve chvíli, kdy se přestane mluvit o technologii a začne o procesu.
Kdy synchronní API
Synchronní volání je správná volba, když:
- Volající bez odpovědi nemůže pokračovat. Ověření limitu před potvrzením obchodu, výpočet ceny v kalkulaci, kontrola oprávnění. Čekání tady k operaci prostě patří.
- Chybu chcete řešit hned a v kontextu. Synchronní volání vrátí chybu tomu, kdo se ptal, ve chvíli, kdy se ptal — a ten může hned reagovat: opravit vstup, zkusit to znovu, říct to uživateli.
- Tok má být čitelný. Řetěz synchronních volání se čte shora dolů a pořadí kroků z něj vidíte na první pohled. U procesů, kde na pořadí a srozumitelnosti záleží, to má velkou cenu.
Cena, kterou za to platíte: provázaná dostupnost. Každý článek synchronního řetězu dědí výpadky všech ostatních. Deset služeb s dostupností 99,9 % za sebou dá dohromady 0,999¹⁰ ≈ 99,0 % — z devíti hodin výpadku ročně je najednou osmdesát sedm. A tempo všem určuje ten nejpomalejší.
A pak je tu retry storm: malý výpadek se vlnou opakovaných volání nafoukne do velkého. Přesně tohle se stalo při výpadku DynamoDB v září 2015 — síť se vzpamatovala za okamžik, jenže vlna synchronních retry pak držela metadata službu přetíženou skoro pět hodin a kaskáda s sebou vzala SQS, CloudWatch i autoscaling. O délce výpadku tedy nerozhodla síť, ale architektura okolo ní. A v říjnu 2025 se to samé zopakovalo ve stejném regionu, tentokrát na čtrnáct hodin.
Kdy eventy
Event je správná volba, když:
- Výsledek zajímá víc odběratelů. Uzavřená smlouva zajímá provize, reporting, dokumenty i marketing. Publikovat jeden event je lepší než volat čtyři API — a pátý odběratel se příště přidá, aniž byste sahali do zdroje.
- Producent nemá znát své konzumenty. Event říká „stalo se“, ne „udělej“. Zdrojový systém se nemusí měnit pokaždé, když si výsledek chce odebírat někdo nový. To je na event-driven přístupu to hlavní: životní cykly systémů se od sebe odpojí.
- Špičky zátěže nemají procházet dál. Fronta mezi producentem a konzumentem nápor rozloží v čase, místo aby se valil kaskádou do dalších systémů.
- Proces snese asynchronnost. „Do několika sekund“ většině navazujících kroků stačí — jen to byznys musí vědět a odsouhlasit.
Cena je tentokrát provozní a mentální: eventy se hůř ladí. Tok procesu nevidíte v jednom trace, konzistence je eventuální, objeví se duplicitní doručení a mrtvé zprávy (DLQ). Bez pořádného monitoringu a idempotentních konzumentů se z „moderní architektury“ stane systém, kterému nikdo nerozumí.
K duplicitám jedna věc, kterou je lepší vědět předem: at-least-once doručení je součást kontraktu. SQS i Stripe webhooky to píšou přímo v dokumentaci — občas prostě dorazí ta samá zpráva dvakrát. Konzument, který na druhé doručení odpoví druhou výplatou provize, má chybu v návrhu; s duplicitami měl počítat. Řešení je staré a osvědčené: idempotency key — stejný požadavek se stejným klíčem se provede jen jednou, ať dorazí kolikrát chce.
Šedá zóna a hybridy
Reálný svět málokdy zapadne čistě do jedné škatulky:
- Request-reply přes eventy — volající pošle požadavek do fronty a čeká na odpovědní event. Špičky se vám rozloží v čase, ale zaplatíte za to složitější korelací. Dává smysl u dlouhých operací, ne jako náhrada obyčejného volání.
- Outbox pattern — když potřebujete zapsat do vlastní databáze a zároveň spolehlivě publikovat event, zapište obojí v jedné transakci (event do outbox tabulky) a publikování nechte na samostatném procesu. Řeší klasický problém „zapsáno, ale neodesláno“.
- Synchronní čtení, asynchronní zápis — častý a zdravý kompromis: na aktuální stav se ptáte přes API, změny se rozhlašují eventy.
Cena každé volby
Žádná z možností není zadarmo — liší se jen tím, kde a kdy zaplatíte:
| Hledisko | Synchronní API | Eventy |
|---|---|---|
| Odpověď pro volajícího | okamžitá | žádná / později |
| Vazba mezi systémy | těsná (dostupnost, verze) | volná (jen kontrakt eventu) |
| Chování při špičce | přenáší zátěž dál | rozloží ji frontou |
| Řešení chyb | hned, v kontextu volání | opožděně, mimo kontext |
| Čitelnost toku | vysoká | vyžaduje nástroje |
| Provozní nároky | nižší | vyšší (monitoring, DLQ, idempotence) |
Závěr
Celý rámec se vejde do tří otázek: kdo potřebuje odpověď a kdy, kolik je odběratelů a co se má stát při výpadku. Odpověď na „API, nebo event?“ z nich většinou vypadne sama. A když si dvě části procesu řeknou každá o něco jiného, nic se neděje — každá prostě potřebuje něco jiného.