Вопрос 6 · Раздел 6

Какие HTTP методы идемпотентны?

Идемпотентные методы — это те, которые можно безопасно повторять.

Версии по языкам: English Russian Ukrainian

Junior Level

Идемпотентные методы — это те, которые можно безопасно повторять.

Идемпотентные методы:

Метод Идемпотентен Почему
GET Да Только читает данные, ничего не меняет
HEAD Да Как GET, только без тела ответа
OPTIONS Да Возвращает информацию о поддерживаемых методах
PUT Да Полная замена ресурса. Повтор = тот же результат
DELETE Да Первый удаляет, повторные подтверждают отсутствие

Неидемпотентные методы:

Метод Идемпотентен Почему
POST Нет Каждый вызов может создать новый ресурс
PATCH Зависит Зависит от того, что именно делает PATCH

Примеры:

GET /users/1      — идемпотентен (чтение)
PUT /users/1      — идемпотентен (замена)
DELETE /users/1   — идемпотентен (удаление)
POST /users       — НЕ идемпотентен (создание)

// GET идемпотентен, потому что он только читает.
// PUT идемпотентен, потому что заменяет (заменил один раз — заменил второй раз на то же самое).
// POST не идемпотентен, потому что добавляет (добавил один раз — добавил ещё раз = два объекта).

Middle Level

Безопасные (Safe) методы: GET, HEAD, OPTIONS

Они идемпотентны по определению, так как не должны менять состояние.

Важно: Кэширующие серверы (Varnish, Cloudflare) могут агрессивно кешировать эти методы. Если сделать GET неидемпотентным (например, инкрементирует счётчик), кеш “спрячет” изменения.

Изменяющие идемпотентные методы: PUT, DELETE

  • PUT: Полное замещение. Если установить status = 'ACTIVE' десять раз, статус останется 'ACTIVE'
  • DELETE: Удаление. Первый вызов удаляет, остальные подтверждают отсутствие

Почему POST не идемпотентен?

POST обычно используется для добавления в коллекцию. 5 запросов POST /orders создадут 5 заказов. Из-за неидемпотентности POST нельзя автоматически повторять при сетевом тайм-ауте — это ведёт к проблеме “двойных оплат”.

PATCH: “Зависит от реализации”

  • {"op": "replace", "path": "/age", "value": 30} — идемпотентен
  • {"op": "add", "path": "/tags", "value": "new"}не идемпотентен (при повторе добавится ещё один тег)
// `replace` всегда устанавливает одно и то же значение — повторный вызов безвреден.
// `add` добавляет элемент в коллекцию — каждый повтор добавляет ещё один.

Диагностика

  • 412 Precondition Failed: Используется с If-Match для гарантии идемпотентности PUT/PATCH
  • Всегда делайте два одинаковых вызова DELETE подряд при тестировании API

Senior Level

RFC 9110 и контракт инфраструктуры

Идемпотентность — это контракт между сервером и клиентом, зафиксированный в спецификации RFC 9110. На Senior-уровне важно понимать, как этот контракт влияет на поведение инфраструктуры (прокси, кеши, Service Mesh).

Роль в Service Mesh

Современные системы используют Service Mesh (Istio, Linkerd) с функцией Automatic Retries:

  • Если эндпоинт помечен как идемпотентный — меш автоматически переотправляет запрос при 503 или TCP Timeout
  • Если ошибиться и метод POST будет автоматически повторён — получите дубликаты данных в БД
// Service Mesh (Istio) по умолчанию повторяет только GET, PUT, DELETE.
// POST требует явной аннотации (например, retryOn: retriable-4xx).

Производительность и Оптимизация

Idempotency Budget

В высоконагруженных системах повторы могут вызвать “шторм запросов” (Retry Storm). Если система прилегла, а тысячи клиентов начали повторять идемпотентные запросы — она не поднимется.

Решение: Exponential Backoff и Jitter при повторах, даже для идемпотентных методов.

Edge Cases

Post-Incremental IDs

Если PUT /users/1 генерирует связанные записи (аудит-лог с новыми ID) — это не нарушение идемпотентности. Идемпотентность касается основного ресурса. Внутренние технические ID или системные логи не ломают контракт.

Мониторинг

  • Metric: http_requests_retry_total: Всплеск повторов для неидемпотентных методов — сигнал о критической ошибке
  • Service Mesh конфигурация должна чётко различать идемпотентные и неидемпотентные эндпоинты

🎯 Шпаргалка для интервью

Обязательно знать:

  • Идемпотентные: GET, HEAD, OPTIONS, PUT, DELETE
  • Неидемпотентные: POST (обычно), PATCH (зависит от реализации)
  • Safe методы (GET, HEAD, OPTIONS) идемпотентны по определению — они не меняют состояние
  • PUT идемпотентен: полная замена ресурса даёт одинаковый результат при повторе
  • DELETE идемпотентен: после первого удаления ресурса нет, повторные подтверждают отсутствие
  • PATCH идемпотентен только при детерминированных операциях (replace — да, add — нет)
  • Service Mesh (Istio) автоматически повторяет только идемпотентные запросы при 503
  • Для POST с Idempotency Key в Service Mesh нужна явная аннотация retryOn

Частые уточняющие вопросы:

  • Почему POST нельзя автоматически повторять? — Риск дублирования данных (двойные оплаты, заказы)
  • Как Service Mesh использует идемпотентность? — Автоматически повторяет GET/PUT/DELETE при 503, POST — только с явной конфигурацией
  • Что такое Retry Storm? — Шторм повторов: при падении системы тысячи клиентов одновременно повторяют запросы
  • Почему идемпотентность DELETE не нарушается при генерации аудита? — Идемпотентность касается основного ресурса, а не побочных эффектов

Красные флаги (НЕ говорить):

  • «Все HTTP методы идемпотентны» — POST точно не идемпотентен
  • «DELETE не идемпотентен, потому что второй раз возвращает 404» — состояние сервера одинаково, это идемпотентно
  • «PATCH всегда не идемпотентен» — replace-операция идемпотентна
  • «Идемпотентность — это про код ответа» — это про состояние сервера

Связанные темы:

  • [[Что такое идемпотентность (idempotency)]]
  • [[Почему GET и DELETE идемпотентны]]
  • [[Является ли POST идемпотентным]]
  • [[Какие основные HTTP методы используются в REST]]
  • [[В чём разница между PUT и PATCH]]