🌤
📍 Определение...
📅 25.10.2026
👤 5
← Назад к новостям

Идемпотентность в платёжном конвейере: «повтори запрос» — это архитектура, а не retry

Начну со сцены, которую видел каждый, кто эксплуатировал платёжный сервис хотя бы год.

Клиент нажимает «Оплатить». Приложение отправляет POST /payments. Проходит пять секунд, и HTTP-клиент падает по таймауту. Ретрай-политика, которую кто-то настроил год назад по гайду, ждёт двести миллисекунд и отправляет запрос ещё раз. Через минуту клиент видит в выписке два списания.

На разборе обычно приходят к одному из двух выводов. Оба неверные, хотя второй я сам когда-то считал правильным.

Первый вывод: надо выключить retry на POST. Хорошо, выключили. Теперь у нас платежи, про которые никто не знает, прошли они или нет. Поддержка разбирает их руками. Ущерб никуда не делся, он просто переехал на другой счёт.

Второй вывод: надо добавить заголовок Idempotency-Key. Добавили. Дедупликацию сделали в middleware поверх Redis. Через полгода двойное списание случается снова. Потому что Redis пережил failover и потерял ключи. Или потому что повтор пришёл через сутки из файла клиринга, а в файле никакого HTTP-заголовка нет.

Обе реакции считают идемпотентность свойством одного вызова. На самом деле это свойство контракта между двумя сторонами. И контракт должен доходить без потерь через весь конвейер: от кнопки в приложении до проводки в главной книге и дальше, до файла, который уходит в платёжную схему.

Retry сам по себе всего лишь тактика. Он работает там, где контракт уже есть. Без контракта retry не делает систему устойчивее. Он делает её быстрее ломающейся.

Читать далее
📊 Источник: Habr | Оригинал
← Предыдущая Проектный офис — не отдел отчетности Следующая → Не пишите свой маленький BI