← Назад к вопросам

Почему DELETE-запрос является идемпотентным?

2.0 Middle🔥 111 комментариев
#API и сетевые протоколы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Идемпотентность DELETE-запроса в REST

DELETE - идемпотентный метод. Несколько одинаковых DELETE-запросов должны иметь одинаковый результат.

Определение идемпотентности

Идемпотентный запрос - результат одинаков независимо от количества вызовов:

DELETE /api/v1/users/123 // Первый: удаляет DELETE /api/v1/users/123 // Второй: 404 не найден DELETE /api/v1/users/123 // Третий: 404 не найден

Результат идемпотентен: пользователь удален, повторные вызовы безопасны.

Почему DELETE идемпотентный

f(x) = f(f(x)) = f(f(f(x)))

DELETE удаляет запись:

  • Первый раз: удаляет из БД
  • Второй раз: запись уже удалена, ничего не меняется
  • Третий раз: запись уже удалена, ничего не меняется

Результат всегда одинаков.

HTTP методы и идемпотентность

ИДЕМПОТЕНТНЫЕ:

  • GET: просто читает
  • DELETE: удаляет ресурс
  • PUT: заменяет весь ресурс
  • HEAD: проверка наличия

НЕ ИДЕМПОТЕНТНЫЙ:

  • POST: создаёт новый ресурс (каждый вызов - новая запись)

Практическая реализация

Правильная - идемпотентная: DELETE /api/v1/users/:id возвращает 204 или 404 Оба означают: ресурс удален

Неправильная - НЕ идемпотентная: DELETE отправляет письмо каждый раз 1-й раз: письмо отправлено 2-й раз: письмо не отправлено (ресурс удалён) Результат разный!

Проблемы с сетью

Сценарий: сетевая ошибка при DELETE

  1. Клиент отправляет DELETE /api/v1/users/123
  2. Сервер удаляет пользователя
  3. Ответ потеряется в сети
  4. Клиент повторяет DELETE (не знает что удалено)
  5. Сервер возвращает 404
  6. Но логически все корректно - пользователь удален!

Это безопасно потому что DELETE идемпотентен!

REST стандарт

По RFC 7231, DELETE должен быть идемпотентным.

Статус коды:

  • 204 No Content: успешно удалено (preferred)
  • 200 OK: успешно удалено
  • 404 Not Found: не найден
  • 409 Conflict: конфликт

Клиент может безопасно повторять

async function deleteUserSafely(userId: string) {

let retries = 3;

while (retries > 0) {

    try {
      const response = await fetch(`/api/v1/users/${userId}`, {
        method: 'DELETE'
      });
      
      if (response.status === 204 || response.status === 404) {
        return true; // Оба означают результат достигнут
      }
    } catch (error) {
      retries--;
    }

}

}

Это не проблема потому что DELETE идемпотентен!

Сравнение с POST

POST - НЕ идемпотентный: POST /api/v1/users { name: "John" } 1-й раз: создаёт John #1 2-й раз: создаёт John #2 (дублирование!)

DELETE - идемпотентный: DELETE /api/v1/users/123 1-й раз: удаляет 2-й раз: возвращает 404 (но результат корректен)

Можно безопасно повторять!

Заключение

  1. Математически: f(x) = f(f(x)) - результат одинаков при повторении
  2. Практически: можно безопасно повторять при сетевых ошибках
  3. RFC 7231: DELETE обязан быть идемпотентным
  4. Статус коды: 204 или 404 - оба корректны
  5. Контраст: POST не идемпотентен, каждый вызов создаёт ресурс

Идемпотентность DELETE - основа надёжных REST API.