Klient przypisuje jednej operacji biznesowej stabilny klucz idempotencji, serwer wiąże go z tożsamością i treścią żądania, atomowo zapisuje stan, a przy powtórzeniu zwraca pierwotny wynik lub bezpieczny konflikt. Projekt należy przetestować przy współbieżności, przekroczeniu limitu czasu i częściowej awarii.
Idempotentność API oznacza, że ponowne wykonanie tej samej zamierzonej operacji nie wywoła kolejnego niepożądanego skutku. Jest ważna przy zamówieniu, płatności, fakturze, rezerwacji lub imporcie kontaktu. Klient może powtórzyć żądanie po timeoucie, użytkownik kliknąć dwa razy, a pośrednik dostarczyć zdarzenie wielokrotnie, mimo że pierwsza próba już się powiodła.
Proste sprawdzenie, czy rekord istnieje, może nie wystarczyć przy współbieżności lub częściowej awarii. Projekt wymaga tożsamości operacji, atomowego zapisu stanu, reguł odpowiedzi przy powtórzeniu oraz bezpiecznej naprawy. Idempotencja nie oznacza ignorowania każdego podobnego żądania; dwa rzeczywiście różne zamówienia muszą pozostać odrębne.
Praktyczny przykład: ponowienie partii bez podwójnego zapisu
Przy masowych zmianach na własnej stronie pracujemy z 200 artykułami. Operacja musi więc umieć wznowić działanie po przerwaniu i rozpoznać już przetworzony artykuł. Podstawą jest stabilna tożsamość rekordu, zapisany plan i sprawdzenie aktualnego stanu przed zapisem. Takie samo podejście jest potrzebne przy integracji zamówień przez API.
Poniższy przykład to modelowy projekt API, a nie istniejący endpoint zamówień Webiant. Klient tworzy klucz dla jednej operacji biznesowej i przy powtórzeniu żądania go zachowuje:
POST /orders
Idempotency-Key: objednavka-2026-001
{"external_id":"2026-001","amount_cents":12900,"currency":"EUR"}| Sytuacja | Zachowanie serwera |
|---|---|
| Pierwszy klucz i nowa treść | Atomowo utworzyć zamówienie i zapisać odpowiedź przy kluczu |
| Ten sam klucz i ta sama treść | Zwrócić zapisany wynik bez nowego zamówienia |
| Ten sam klucz, ale inna treść | Odrzucić konflikt; na przykład HTTP 409 zgodnie z kontraktem API |
| Dwa równoczesne żądania | Unikalne ograniczenie w bazie danych i transakcja zapobiegną podwójnemu utworzeniu |
Kontrola „najpierw wyszukaj, potem utwórz” nie wystarcza przy równoczesnych żądaniach. Zapis klucza i operacji biznesowej musi być chroniony transakcją lub równoważną operacją atomową. Jeśli wysyłany jest e-mail lub żądanie płatności, trzeba osobno obsłużyć także ten efekt uboczny.
Test przed przekazaniem integracji
- Proszę wysłać to samo żądanie dwukrotnie i porównać ID wyniku.
- Ponów żądanie po symulowanym przekroczeniu limitu czasu.
- Wyślijcie jednocześnie dwa identyczne żądania.
- Proszę zmienić treść przy tym samym kluczu i zweryfikować uzgodnione rozwiązanie konfliktu.
- Proszę sprawdzić, czy e-mail, płatność lub rekord w CRM nie powstanie dwukrotnie.
Przy własnej integracji warto uzgodnić także czas przechowywania kluczy i zasady ponawiania. Wiąże się z tym mapowanie danych między systemami.
Zrozum, skąd bierze się powtarzanie
Klient HTTP często nie wie, czy timeout nastąpił przed przetworzeniem żądania, czy po nim. Ponawianie jest więc naturalną strategią, a nie błędem. Niektóre kolejki i mechanizmy webhooków są zaprojektowane tak, aby dostarczać komunikaty co najmniej raz, co świadomie dopuszcza duplikaty. Podwójne kliknięcie użytkownika, cofnięcie w przeglądarce czy ponowny import tworzą kolejne ścieżki prowadzące do tego samego efektu.
Zmapuj operacje, w których duplikat powoduje problem biznesowy. Odczyt zwykle nie niesie takiego samego ryzyka jak utworzenie płatności. Aktualizacja do konkretnej wartości zachowuje się inaczej niż polecenie zwiększenia ilości. Dla każdej operacji określ tożsamość intencji i okres, w którym powtórzenie uznaje się za tę samą operację.
Zaprojektuj stabilny klucz idempotentny
Klucz powinien powstać jeden raz dla konkretnego zamiaru biznesowego i pozostać taki sam przy technicznym ponowieniu. Nie należy generować go od nowa przy każdej próbie, w przeciwnym razie serwer nie rozpozna duplikatu. Zakres klucza należy powiązać z klientem, kontem lub endpointem, aby przypadkowa zbieżność między różnymi użytkownikami nie stała się konfliktem.
Serwer może zapisać odcisk istotnej treści i odrzucić ten sam klucz z innymi parametrami. Chroni w ten sposób klienta przed pomyłką, gdy ponownie użyje klucza dla innej kwoty lub produktu. Nie uwzględniaj w porównaniu wartości, które naturalnie zmieniają się przy każdej próbie, na przykład technicznego znacznika czasu.
- jedno słowo kluczowe dla jednego celu biznesowego
- powiązanie z klientem i typem operacji
- kontrola zmienionej treści
- jasny okres przechowywania stanu
Zapisuj stan i wynik atomowo
Przy pierwszym odebraniu utwórz rekord operacji w sposób, który uniemożliwi dwóm równoległym procesom roboczym przejęcie własności. Unikalny klucz w bazie danych lub mechanizm transakcyjny jest bardziej niezawodny niż oddzielne „najpierw sprawdź, potem wstaw”. Stan może rozróżniać operacje odebrane, przetwarzane, zakończone sukcesem i nieudane.
Po powodzeniu należy zachować bezpieczny wynik lub odwołanie do utworzonego obiektu. Powtórzone żądanie powinno otrzymać spójną odpowiedź bez dodatkowego efektu. Przy długotrwałej pracy serwer może poinformować, że operacja trwa, i udostępnić endpoint statusu. Nie należy przechowywać zbędnych wrażliwych treści wyłącznie ze względu na idempotencję.
Proszę obsłużyć częściowy sukces i kolejność kroków
Operacja może zapisać zamówienie, a następnie zakończyć się niepowodzeniem przy wysyłce e-maila lub wywołaniu zewnętrznego API. Odróżnij główne zobowiązanie biznesowe od zadań następczych. Kroki poboczne obsługuj przez odporną kolejkę i również nadaj im własną tożsamość. Anulowanie całego wyniku po przyjęciu płatności może być niemożliwe lub niewłaściwe.
Jeśli ten sam obiekt jest zmieniany przez wiele zdarzeń, sama idempotencja nie rozwiąże problemu ich kolejności. Należy użyć wersji, oczekiwanego stanu lub sekwencyjnego przetwarzania w obrębie obiektu. Starsze zdarzenie nie powinno nadpisać nowszego stanu końcowego. Konflikt warto uwidocznić do ręcznej decyzji, jeśli nie da się go bezpiecznie rozwiązać regułą.
Testuj współbieżność, wygaśnięcie i naprawę
To samo żądanie należy uruchomić równolegle, przerwać połączenie po wysłaniu i powtórzyć je zarówno w trakcie przetwarzania, jak i po sukcesie. Trzeba sprawdzić ten sam klucz z inną treścią, nieprawidłowego klienta oraz powtórzenie po upływie okna retencji. Kontroli podlega wynik biznesowy, stan magazynu, dokument i zdarzenia, a nie tylko kod statusu.
Zespół operacyjny musi widzieć operacje, które utknęły w przetwarzaniu, i bezpiecznie decydować o ich kontynuacji. Ręczne usunięcie rekordu idempotencji może wywołać duplikat, dlatego utwórz kontrolowaną procedurę naprawczą. Monitoruj odsetek ponowień; nagły wzrost może sygnalizować timeout, błąd klienta lub problem z siecią.
- dwie równoczesne próby z tym samym kluczem
- timeout po pomyślnym zapisaniu obiektu biznesowego
- ten sam klucz z inną treścią
- częściowy sukces powiązanej operacji zewnętrznej
- kontrolowane ponowienie po ręcznej poprawce
- wygaśnięcie zapisanego klucza podczas przywracania usługi
- bezpieczny konflikt przy nieprawidłowej tożsamości klienta
- jeden dokument wynikowy we wszystkich systemach
Najczęstsze pytania
Czy idempotencja to to samo co deduplikacja?
Są powiązane, ale nie tożsame. Idempotencja wiąże powtarzane próby techniczne z jedną intencją i wynikiem. Deduplikacja może później łączyć odrębne rekordy na podstawie podobieństwa lub reguł biznesowych.
Kto powinien utworzyć klucz idempotentności?
Zwykle klient, który zna granicę jednej intencji i potrafi ponownie użyć klucza. Serwer określa format, zakres, walidację i okres przechowywania zgodnie z kontraktem API.
Jak długo przechowywać wynik operacji?
Według najdłuższego realistycznego okresu ponowień, ryzyka biznesowego i kosztów przechowywania. Reguła retencji musi być udokumentowana; po jej upływie ten sam klucz może oznaczać nowy wynik.