Strona główna / Warto wiedzieć ! / Dlaczego Twój SaaS traci na złej architekturze eventów? 3 lekcje

Dlaczego Twój SaaS traci na złej architekturze eventów? 3 lekcje

Dlaczego Twój SaaS traci na złej architekturze eventów? 3 lekcje z backendu

Event-driven architecture (EDA) brzmi jak odpowiedź na wszystkie problemy skalowalności. W teorii – asynchroniczność, luźne powiązania, łatwe dodawanie nowych funkcji. W praktyce – widziałem już kilka systemów, które po wdrożeniu EDA generowały więcej problemów niż rozwiązywały. Często słyszę od CTO: „przeszliśmy na eventy, ale aplikacja stała się wolniejsza, a debugowanie – koszmarem”. Dlaczego? Bo architektura eventów nie polega tylko na wrzuceniu kolejki i nadawaniu nazw. To decyzje o spójności, kolejności, obsłudze błędów i idempotentności. W tym artykule pokazuję trzy realne błędy, które widziałem w SaaS-ach średniej wielkości – i jak je rozwiązać.

1. Utrata kolejności eventów – cichy zabójca spójności danych

Wyobraź sobie system zamówień w e-commerce. Klient składa zamówienie, potem anuluje, a po chwili zmienia adres dostawy. Kolejność ma znaczenie: najpierw tworzymy zamówienie, potem anulujemy, potem aktualizujemy – ale aktualizacja powinna zostać odrzucona, bo zamówienie jest anulowane. Jeśli eventy trafią do kolejki w innej kolejności (np. z powodu opóźnienia sieciowego lub restarta konsumenta), możesz skończyć z zamówieniem „zaakceptowanym” po anulacji.

Przykład z życia: Klient – SaaS do zarządzania subskrypcjami. Mieli problem: użytkownicy otrzymywali maile z potwierdzeniem zmiany planu, które były wysyłane przed faktyczną zmianą w systemie. Powód? Eventy wysyłane asynchronicznie, ale konsument przetwarzał je równolegle, a kolejność gwarantowana była tylko w ramach jednej partycji – której nie ustawili. Rozwiązanie? Wprowadzenie sequence number lub użycie event sourcingu z agregacją stanu. Prościej: wybór brokera z gwarancją kolejności (np. Kafka z kluczem partycji) albo zastosowanie outbox pattern z zachowaniem kolejności w bazie danych.

Lekcja: Jeśli kolejność eventów ma znaczenie (a prawie zawsze ma dla spójności danych), nie zakładaj, że kolejka jest domyślnie FIFO. Zaprojektuj mechanizm weryfikacji – wersjonowanie eventów, timestampy, a najlepiej – używaj zdarzeń, które niosą pełny stan, a nie tylko różnicę.

2. Brak idempotentności – podwójne opłaty i zduplikowane maile

Każdy system dystrybucyjny ma opóźnienia, timeouty, retransmisje. Jeśli konsument eventu nie jest idempotentny, pojedyncze zdarzenie może być przetworzone wielokrotnie. W SaaS oznacza to: naliczenie opłaty dwa razy, wysłanie dwóch maili, utworzenie dwóch rekordów.

Przykład z życia: Startup fintechowy – system rozliczeń dla subskrypcji. Broker wysyłał event „payment.success”, ale przy problemach sieciowych – zdarzały się duplikaty. System tworzył nowy rekord płatności za każdym razem. Klient widział podwójne obciążenie na karcie, a support tonął w reklamacjach. Rozwiązanie? Każdy event musi mieć unikalny identyfikator (np. UUID), a konsument sprawdzać, czy już przetworzył event o danym ID. Można to zrobić w bazie danych (UNIQUE constraint) lub w pamięci (np. Redis TTL).

Lekcja: Zawsze zakładaj, że event może być dostarczony więcej niż raz. Wprowadź idempotentność na poziomie konsumenta. Używaj deduplikacji po stronie odbiorcy, a nie brokera.

3. Eventy zbyt szczegółowe lub zbyt ogólne – balans między granularnością a kosztem

Częsty dylemat: jak duży powinien być event? Jedni tworzą mikro-eventy („kolorZmieniony”, „adresZaktualizowany”) – to zalewa system setkami zdarzeń. Inni wysyłają jeden wielki „obiektZmieniony” z całym stanem – to zmusza konsumentów do parsowania i przetwarzania niepotrzebnych danych, a także zwiększa rozmiar wiadomości i opóźnienia.

Przykład z życia: Platforma SaaS do zarządzania projektami. Zdefiniowali event „taskUpdated” zawierający tylko ID zadania. Każdy konsument musiał robić osobne zapytanie do API, aby pobrać pełne dane. Skutek: lawina zapytań, opóźnienia, wysoki koszt operacji. Po zmianie na eventy zawierające pełny stan (np. „taskUpdated” z polem „status”, „assignee”, „dueDate”) – konsumenci przetwarzali dane lokalnie, bez dodatkowych zapytań. Z drugiej strony, inny klient zrobił jeden event „userChanged” dla każdej zmiany użytkownika – konsumenci otrzymywali cały obiekt, ale tylko 10% danych było faktycznie używane, więc marnowali przepustowość.

Lekcja: Znajdź złoty środek. Używaj selector eventów – każdy event niech zawiera tylko pola istotne dla konsumentów. Jeśli masz różne konsumenty potrzebujące różnych danych, rozważ wysyłanie kilku typów eventów (np. „taskStatusChanged” dla powiadomień, „taskUpdated” dla synchronizacji). Unikaj jednak przesadnej granularności – zbyt wiele typów eventów zwiększa złożoność zarządzania.

Podsumowanie

Architektura eventowa to potężne narzędzie, ale wymaga świadomych decyzji. Kolejność, idempotentność i odpowiednia granularność to trzy filary, które decydują o tym, czy EDA przyniesie korzyści, czy stanie się źródłem kosztów. Zanim wdrożysz kolejki i tematy, zastanów się nad konsekwencjami dla spójności danych i łatwości debugowania.

Jeśli Twój SaaS boryka się z problemami skalowalności lub niezawodności – warto spojrzeć na architekturę eventów pod tym kątem. W JurskiTech.pl pomagamy firmom projektować systemy, które rosną bez bólu. A jeśli masz wątpliwości – przyjdź z kodem, pogadamy.

Tagi:

Zostaw odpowiedź

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *