Wstęp
Event Driven Architecture (EDA) obiecuje elastyczność, skalowalność i luźne powiązania między serwisami. Brzmi jak ideał dla każdego SaaS, który dynamicznie rośnie. Jednak z mojej praktyki wynika, że w większości wdrożeń EDA kończy się… gorzej niż monolit. Nie dlatego, że idea jest zła, ale dlatego, że implementacja kuleje. Klienci przychodzą do nas po audycie z typowymi objawami: system działa wolno, eventy się gubią, trudno debugować, a koszty chmury rosną w sposób niekontrolowany. W tym artykule pokażę trzy kluczowe błędy, które popełniają nawet doświadczone zespoły, i jak ich uniknąć.
1. Brak strategii obsługi błędów w event loop
Pierwszy błąd to traktowanie systemu eventowego jak czarnej skrzynki. Zespoły często zakładają, że skoro event został wysłany, to na pewno zostanie przetworzony. A potem zdarza się katastrofa: awaria brokera, tymczasowa niedostępność konsumenta, błąd deserializacji. I co wtedy? Najczęściej event ginie w czeluściach logów, a klient traci zamówienie, dane lub spójność.
Przykład z życia: Klient (firma SaaS z branży e-commerce) wdrożył eventy dla aktualizacji stanów magazynowych. Przy wysyłce zamówienia system wysyłał event do zarezerwowania towaru. Broker – RabbitMQ – z jakiegoś powodu zwrócił błąd, ale aplikacja nie miała żadnej procedury retry. Rezultat: zamówienie przeszło, ale stan magazynowy nie został zaktualizowany. Magazyn wysłał produkt, który fizycznie nie istniał. Klient musiał ręcznie anulować setki zamówień.
Jak to zrobić dobrze? Każdy event powinien mieć mechanizm powtórek (retry) z backoffem, a po wyczerpaniu prób – trafić do Dead Letter Queue (DLQ). Nawet jeśli brzmi to jak dodatkowa praca, to właśnie ta warstwa ratuje biznes. W praktyce warto też monitorować wiek eventów w DLQ i alertować, jeśli zaczynają się starzeć.
2. Niedopasowanie semantyki eventów do kontekstu biznesowego
Drugi błąd to projektowanie eventów wokół struktur danych z bazy, a nie wokół zdarzeń biznesowych. Często widzę eventy takie jak UserUpdated, OrderModified czy ProductChanged. To są eventy techniczne, które mówią: „coś się zmieniło w tabeli”. Ale nie mówią, co się stało w biznesie. A to ma kluczowe znaczenie dla odbiorców.
Przykład: W jednym SaaS do zarządzania subskrypcjami system wysyłał event SubscriptionUpdated za każdym razem, gdy zmieniało się pole w bazie. Odbiorcy (np. serwis billingowy czy system dostępu) nie wiedzieli, czy chodzi o przedłużenie, anulację, czy downgrade. Każdy odbiorca musiał parsować JSON i domyślać się intencji. Efekt? Błędy w naliczaniu opłat, niekonsystencje, a developerzy spędzali godziny na debugowaniu.
Rozwiązanie: Zamiast SubscriptionUpdated podziel na SubscriptionStarted, SubscriptionCanceled, SubscriptionDowngraded, SubscriptionPaymentFailed. Każdy z tych eventów ma jasne znaczenie biznesowe i zawiera tylko te dane, które są potrzebne. Odbiorcy nie muszą analizować różnic – dostają gotową informację. To pozornie drobna zmiana, ale redukuje błędy i czas developmentu.
Dodatkowo unikaj nadmiernego rozrastania się eventów: nie dodawaj do eventu wszystkich pól z bazy, tylko to, co jest konieczne dla odbiorców. To zmniejsza rozmiar wiadomości, obciążenie sieci i ułatwia ewolucję schematów.
3. Brak celowania w skalowalność konsumentów
Trzeci błąd to projektowanie konsumentów eventów tak, jakby były monolitycznymi odbiornikami. Często widzę aplikację, która subskrybuje eventy z kilku źródeł i przetwarza je w jednym procesie. Gdy rośnie liczba eventów, konsument staje się wąskim gardłem, a kolejka eventów rośnie. Zamiast skalować poziomo (dodając więcej instancji konsumenta), zespół próbuje optymalizować jednowątkowy kod, co nie przynosi efektu.
Przykład: Firma z branży fintech miała system rekomendacji, który nasłuchiwał eventów z kilku mikroserwisów. Konsument był jednym procesem Node.js. Gdy w black friday ilość eventów wzrosła stukrotnie, proces nie nadążał, eventy zaczęły timeoutować, a broker stracił część wiadomości. Klient stracił dane o zakupach, a rekomendacje na stronie głównej przestały działać.
Jak to zrobić dobrze? Konsument powinien być bezstanowy i skalowalny horyzontalnie. Użyj wzorca „competing consumers” – wiele instancji tego samego serwisu czyta z tej samej kolejki, każda przetwarza inne eventy. Pamiętaj też o idempotentności: każdy event powinien być bezpieczny do ponownego przetworzenia. Nawet jeśli konsument przetworzy go dwa razy (np. po restarcie), system musi pozostać spójny. Najprostsze: sprawdzaj, czy event już został obsłużony (np. po ID eventu) lub zapewnij operacje idempotentne (np. zapis do bazy z operacją UPSERT).
Podsumowanie
Event Driven Architecture to potężne narzędzie, ale wymaga dyscypliny. Prawdziwym wyzwaniem nie są same eventy, tylko projektowanie systemu wokół nich. Unikniesz kosztownych błędów, jeśli:
- Zadbasz o obsługę błędów i Dead Letter Queue.
- Zaprojektujesz eventy wokół zdarzeń biznesowych, a nie zmian w bazie.
- Uczynisz konsumentów bezstanowymi i skalowalnymi horyzontalnie.
Z mojego doświadczenia: firmom, które wdrażają te zasady, udaje się skalować SaaS bez utraty kontroli nad kosztami i jakością. Jeśli Twój system oparty na eventach zaczyna sprawiać ból – warto zrobić audyt pod kątem tych trzech punktów. Często okazuje się, że wystarczy kilka zmian, by tchnąć nowe życie w architekturę.
A jakie błędy Ty najczęściej widzisz w implementacji EDA? Podziel się w komentarzu – chętnie przedyskutujemy.


