Повторный webhook не должен создавать второй заказ, второй платёж и второй баг
Идемпотентность — это не «красивое слово из архитектуры», а защита от дублей, которые неизбежны при ретраях, таймаутах и кривых клиентах. Смотрим в тело запроса: если внешний сервис прислал payload второй раз, ваш хендлер обязан вернуть тот же результат, а не выполнить бизнес-операцию повторно.
Базовый паттерн простой: у каждого события должен быть idempotency key. Это может быть request_id, event_id или хэш канонизированного JSON. Ключ кладём в отдельное хранилище с уникальным индексом: сначала пытаемся записать, потом выполняем действие. Если запись уже есть — сразу отдаём сохранённый ответ или статус обработки.
Типовая схема: `POST /webhook` → проверка подписи → дедупликация → очередь → воркер. Если воркер упал после записи в БД, но до ответа внешнему сервису, повторный запрос не должен повторно списывать деньги. Ретрай-политика решает всё: повторяем только безопасные операции, а для side effect’ов держим транзакцию, outbox или хотя бы таблицу processed_events. ⚙️
Не путайте идемпотентность с «ну у нас просто стоит if exists». Проверка должна быть атомарной, иначе два параллельных запроса пройдут гонку и вы получите двойное исполнение. Идемпотентность — это не роскошь, а база: уникальный ключ, атомарная запись, сохранённый ответ, понятные статусы обработки.
Дубли лечатся не логикой «авось пронесёт», а структурой данных и порядком операций. Пока у вас нет жёсткого дедупа, каждый повторный запрос — это потенциальный инцидент.
Автоматизация на вебхуках
@webhook_automation_hub_arb
Повторный webhook не должен создавать второй заказ, второй платёж и второй баг
Этот пост опубликован в Telegram-канале Автоматизация на вебхуках. Подписаться можно по ссылке: @webhook_automation_hub_arb.