Идемпотентность endpoint-а пополнения баланса
Пользователь повторно отправил запрос на пополнение баланса. Как сделать endpoint идемпотентным?
Ответить самому
Сначала сформулируйте ответ как на собеседовании, затем откройте разбор и оцените себя.
Короткий ответ
Клиент присылает idempotency key, сервер хранит результат первого выполнения и при повторе возвращает тот же результат, не меняя баланс второй раз.
Полный разбор
Для операции с деньгами retry неизбежен: клиент мог не получить ответ, сеть оборвалась, gateway повторил запрос. Поэтому логический запрос должен иметь idempotency key. Сервер в транзакции проверяет, был ли такой key для этого пользователя/операции.
Если key новый, сервер выполняет операцию, записывает изменение баланса и сохраняет результат: status, operation id, amount, response payload. Если key уже был, сервер не делает новое начисление, а возвращает сохраненный результат. Важно ограничить scope ключа, например user_id + operation_type + key, и хранить TTL.
Нужны уникальный индекс в БД, транзакции, защита от concurrent duplicate requests и понятная обработка intermediate state: если первая попытка зависла, повтор должен либо дождаться результата, либо вернуть retryable статус без двойного списания/начисления.
Теория
Идемпотентность делает повтор одного логического запроса безопасным для состояния системы.
Типичные ошибки
- Генерировать idempotency key на сервере после получения запроса.
- Проверять дубликат вне транзакции без unique constraint.
- Не сохранять response первого выполнения.