Wstęp: Kiedy system przestaje nadążać
Pracowałem ostatnio z klientem, który prowadzi sklep e-commerce z kilkudziesięcioma tysiącami transakcji dziennie. Wszystko działało dobrze – do czasu gdy wprowadzili kilka nowych integracji: płatności BNPL, system lojalnościowy, zewnętrzny fulfillment. Nagle czas odpowiedzi API zaczął rosnąć, a w szczycie pojawiały się timeouty. Klient był przekonany, że to wina hostingu. Po audycie okazało się, że problemem była architektura: każda operacja wywoływała szereg synchronicznych zależności, które blokowały główny wątek.
Rozwiązaniem była architektura event-driven. Ale czy każda implementacja kończy się sukcesem? Niestety nie. Widziałem wiele firm, które wdrożyły event-driven i… wpadły w nowe pułapki. W tym artykule pokażę 3 najczęstsze błędy, które zabijają skalowalność w e-commerce.
Czym jest event-driven w e-commerce?
Zanim przejdziemy do błędów – krótkie przypomnienie. W architekturze event-driven zamiast wywoływać usługi synchronicznie (np. po złożeniu zamówienia wywołujemy system magazynowy, potem płatności, potem wysyłkę), generujemy zdarzenie (np. „order.placed”) i wysyłamy je do brokera (np. Kafka, RabbitMQ, AWS EventBridge). Każda usługa subskrybuje interesujące ją zdarzenia i reaguje asynchronicznie.
Dzięki temu system staje się luźno powiązany, łatwiej skalowalny i bardziej odporny na awarie. Ale diabeł tkwi w szczegółach.
Błąd #1: Zbyt wiele synchronicznych zależności w event-handlerach
To najbardziej klasyczny błąd. Firma wdraża event-driven, ale w handlerach zdarzeń nadal wykonuje synchroniczne zapytania do innych usług. Na przykład: po zdarzeniu „order.placed” handler systemu lojalnościowego potrzebuje danych klienta z bazy CRM. Zamiast wcześniej wzbogacić zdarzenie o dane klienta, handler wykonuje synchroniczny request do CRM. Gdy CRM jest wolny, cały event się opóźnia. A gdy CRM pada, event się gubi.
Przykład z życia: Klient z sektora fashion miał system, w którym każde zdarzenie „order.placed” wywoływało 3 synchroniczne zapytania do różnych serwisów. W szczycie sezonu broker eventów zalał się, a kolejka rosła. Rozwiązanie? Wzbogacanie eventów o dane niezbędne do przetworzenia (enrichment) oraz wprowadzenie dedykowanych widoków danych (materialized views) w każdej usłudze.
Konsekwencje: Opóźnienia, gubienie eventów, utrata zamówień. W e-commerce każda sekunda zwłoki kosztuje konwersję.
Błąd #2: Brak strategii na eventy nieudane (failed events)
Event-driven nie oznacza, że wszystko zawsze działa. Czasami handler nie przetworzy eventu – błąd w logice, chwilowa niedostępność bazy, błędne dane. I co wtedy? Wiele firm po prostu loguje błąd i… nic nie robi. Albo próbuje ponownie w nieskończoność, zaśmiecając kolejkę.
Prawidłowe podejście: Wdrożenie dead letter queue (DLQ) – osobnej kolejki dla eventów, które nie udało się przetworzyć po kilku próbach. Należy też określić politykę ponawiania: liczba prób, backoff (np. wykładniczy), timeouty. Dodatkowo warto monitorować DLQ i alertować, gdy liczba nieudanych eventów przekracza próg.
Przykład z życia: Sklep z elektroniką stracił 5% zamówień, bo eventy „payment.success” nie docierały do systemu wysyłkowego. Przyczyną był błąd walidacji danych (nieprawidłowy format adresu). Eventy lądowały w black hole – logowały się, ale nie trafiały do DLQ. Dopiero po dodaniu DLQ i monitoringu wykryto problem i naprawiono walidację.
Konsekwencje: Utrata zamówień, niezrealizowane wysyłki, spadek reputacji.
Błąd #3: Niewłaściwe zarządzanie kolejnością eventów
W e-commerce często zdarzenia muszą być przetwarzane w określonej kolejności. Na przykład: najpierw „payment.pending”, potem „payment.success”, a dopiero potem „order.shipped”. Jeśli kolejność zostanie zachwiana, system może wysłać przesyłkę przed potwierdzeniem płatności.
Architektura event-driven domyślnie nie gwarantuje kolejności – zwłaszcza gdy używamy wielu partycji. Rozwiązaniem jest stosowanie key-based partitioning (np. identyfikator zamówienia jako klucz partycji), aby wszystkie eventy dla danego zamówienia trafiały do tej samej partycji i były przetwarzane sekwencyjnie. Alternatywnie można używać dedykowanych narzędzi do event sourcing lub sagas.
Przykład z życia: Klient wdrożył Kafkę dla usługi płatności. Użyli domyślnego hashowania klucza, ale kluczem był UUID zamówienia, co rozrzucało eventy po wszystkich partycjach. W efekcie przetwarzanie równoległe powodowało, że czasami „order.shipped” był przetwarzany przed „payment.success”. Na szczęście mieli zabezpieczenia w logice biznesowej, ale opóźnienia były znaczne.
Konsekwencje: Błędy logiczne, problemy z transakcjami, trudne do debugowania.
Podsumowanie: Jak uniknąć tych błędów?
Architektura event-driven to potężne narzędzie, ale wymaga przemyślanego projektu. Oto trzy kluczowe zasady:
- Wzbogacaj eventy, nie wywołuj synchronicznie – jeśli handler potrzebuje danych, dodaj je do eventu lub użyj widoków lokalnych.
- Zaimplementuj DLQ i monitoring – nieudane eventy nie mogą ginąć. Bez DLQ tracisz kontrolę.
- Zadbaj o kolejność – używaj odpowiedniego klucza partycji, a jeśli potrzebujesz sekwencyjności, rozważ sagas lub event sourcing.
W JurskiTech regularnie pomagamy firmom przejść na architekturę event-driven lub poprawić istniejące implementacje. Często okazuje się, że problem nie leży w samym narzędziu, ale w projekcie. Jeśli rozwijasz e-commerce i czujesz, że architektura zaczyna Cię ograniczać – warto spojrzeć na nią krytycznie. Event-driven może być zbawieniem, ale tylko jeśli zrobisz to dobrze.


