Dlaczego zdarzenia z webhooków przychodzą więcej niż raz i jak sprawić, by ich przetwarzanie było idempotentne?
Zakładaj, że webhooki dostarczają zdarzenia co najmniej raz (at-least-once) i że utracone potwierdzenia odbioru mogą tworzyć duplikaty. Zanim wykonasz efekty uboczne, odsiej duplikaty na podstawie stabilnego identyfikatora zdarzenia od dostawcy — takiego jak sg_event_id czy svix-id. Wstrzymaj nieidempotentne efekty uboczne w dalszych etapach, dopóki powtórzone identyfikatory nie będą bezpiecznie ignorowane.
Pierwsze 15 minut
- Porównaj zdublowane ładunki (payload) SendGrid po sg_event_id, gdy to pole jest dołączone.
- Sprawdź odpowiedzi Event Webhook inne niż 2xx — to one wyzwalają ponowienia SendGrid nawet przez 24 godziny.
- Porównaj duplikaty z Resend po svix-id i potwierdź, że już przetworzone identyfikatory są pomijane.
Teraz
- Zapisuj i pomijaj powtórzone wartości sg_event_id lub svix-id, zanim wykonasz efekty uboczne w dalszych etapach.
Najbliższe 24 godziny
- Połącz utrwalanie identyfikatora zdarzenia i sam efekt uboczny w jedną, idempotentną ścieżkę przetwarzania.
Najbliższe 7 dni
- Używaj znacznika czasu zdarzenia od dostawcy, gdy stan aplikacji zależy od kolejności zdarzeń, bo Resend nie gwarantuje kolejności dostarczania.
Kontrole techniczne
Inżynieria
- Zapisuj na trwałe wartości sg_event_id z SendGrid i odsiewaj ich duplikaty, gdy są dołączone.
- Potwierdź, że po udanym przetworzeniu endpoint SendGrid zwraca odpowiedź 2xx, żeby nie wyzwalać ponowień właściwych dla odpowiedzi innych niż 2xx.
- Gdy musisz odtworzyć kolejność zdarzeń, użyj znacznika czasu created_at z Resend zamiast kolejności ich nadejścia.
Kryteria weryfikacji
- Ponów ładunki z tym samym sg_event_id i potwierdź, że efekt uboczny w dalszym etapie wykona się tylko raz.
- Potwierdź, że udane przetwarzanie w SendGrid zwraca 2xx i że nie trwa żadna sekwencja ponowień właściwa dla odpowiedzi innych niż 2xx.
- Ponów zapisany svix-id z Resend i potwierdź, że zostaje pominięty jako już przetworzony.
Kryteria eskalacji
- Eskaluj sprawę wewnętrznie, gdy — już po włączeniu lokalnej deduplikacji — powtórzone sg_event_id nie zostaje pominięte i wykonuje efekt uboczny w dalszym etapie.
- Gdy potwierdzisz, że zapisany svix-id zostaje pominięty, a efekt uboczny w dalszym etapie wykonuje się raz, kolejne dostarczenia tego identyfikatora traktuj jako udokumentowane zachowanie at-least-once, a nie warunek eskalacji.
Zapobieganie
- Traktuj sg_event_id z SendGrid jako klucz deduplikacji, gdy jest dołączony.
- Zapisuj wartości svix-id z Resend i pomijaj już przetworzone identyfikatory.
- Używaj created_at zamiast kolejności nadejścia tam, gdzie kolejność zdarzeń Resend ma znaczenie.
Wpływ na biznes
- Dostarczanie co najmniej raz (at-least-once) może powtórzyć efekty uboczne w dalszych etapach, gdy utracone potwierdzenie odbioru sprawia, że dostawca ponownie dostarcza to samo zdarzenie.
Uwagi dostawcy
- SendGrid ponawia żądania POST do Event Webhook po odpowiedziach innych niż 2xx, w rosnących odstępach, nawet przez 24 godziny.
- Resend dostarcza co najmniej raz (at-least-once) i nie gwarantuje kolejności dostarczania.
Otwarte pytania
- Nazwy pól z identyfikatorem zdarzenia, harmonogramy ponowień, narzędzia do ponawiania i gwarancje kolejności różnią się w zależności od ESP i konkretnego produktu webhookowego.
- To, czy obecne duplikaty mają ten sam identyfikator zdarzenia od dostawcy, czy są odrębnymi zdarzeniami upstream, wymaga analizy ładunku i warstwy trwałego zapisu.
- Moment, w którym obecny handler potwierdza odbiór, oraz jego atomowość względem efektów ubocznych pozostają nieznane, dopóki nie przejrzysz kodu i transakcji bazodanowych.
Źródła (4)
- Twilio SendGrid Event Webhook Overview — Duplicate eventsTwilio SendGrid
- Twilio SendGrid Event Webhook Overview — General troubleshootingTwilio SendGrid
- Managing Webhooks — FAQ: What are the delivery guarantees?Resend
- Managing Webhooks — FAQ: Do events arrive in order?Resend


