← Паттерны приложений
11 мин · средне · Урок 5 из 5

Идемпотентность в API

Почему повторный запрос не должен создавать дубль: идемпотентные методы, ключ идемпотентности и безопасные ретраи.

Проблема повтора

Клиент отправил POST /orders, сеть моргнула, ответ не дошёл. Клиент не знает, создался заказ или нет, и повторяет запрос. Если сервер на каждый POST создаёт новый заказ, повтор делает второй. Прошлый урок про ретраи именно поэтому запрещал повторять POST вслепую. Решение этой проблемы и есть идемпотентность.

Идемпотентная операция даёт один и тот же результат, сколько бы раз её ни повторили. Один заказ остаётся одним заказом, повторили запрос или нет.

Какие методы идемпотентны сами по себе

Из урока про HTTP-методы:

Поэтому где можно, выбирают идемпотентный метод. Создать ресурс с заранее известным id можно через PUT /orders/{id}: повтор просто перезапишет тот же заказ, а не создаст второй.

Ключ идемпотентности

Когда нужен именно POST (id выдаёт сервер), применяют idempotency key. Клиент генерирует уникальный ключ на операцию и шлёт его в заголовке:

POST /orders
Idempotency-Key: 9f1c-44a2-...

{ "item": "book", "qty": 1 }

Сервер запоминает обработанные ключи. Пришёл запрос с уже виденным ключом, и сервер не создаёт новый заказ, а возвращает результат первого. Повтор безопасен: тот же ключ, тот же заказ. Так делают платёжные API, где дубль это списанные дважды деньги.

1-й запрос: ключ новый  → создаём заказ, сохраняем (ключ → заказ)
2-й запрос: ключ виден  → возвращаем тот же заказ, ничего не создаём

Ключи хранят с истечением (например, сутки): дольше держать незачем, а повторы приходят в пределах коротких ретраев.

Зачем это вместе с ретраями

Идемпотентность и ретраи работают в паре. Ретрай из прошлого урока повторяет неудавшийся запрос, а идемпотентность гарантирует, что повтор не навредит. Без идемпотентности ретрай POST опасен; с ключом идемпотентности его можно безопасно повторять, как GET.

То же касается обработчиков очередей: сообщение может прийти повторно (at-least-once доставка), и обработчик должен быть идемпотентным, иначе одно событие применится дважды.

Что важно запомнить

Повтор запроса не должен создавать дубль. GET, PUT, DELETE идемпотентны сами; где можно, создание делают через PUT с известным id.

Для POST применяют idempotency key: сервер запоминает ключ и на повтор возвращает результат первого вызова, не создавая новое. Так защищают платежи и заказы.

Идемпотентность делает ретраи безопасными и обязательна для обработчиков очередей с доставкой at-least-once.

Этим закрывается трек про паттерны приложения: graceful shutdown, health-эндпоинты, конфиг, устойчивость и идемпотентность.

Прошли материал до конца? Отметьте урок пройденным.