Повторные запросы и идемпотентность API: как не создавать дубли при интеграции

Сетевая интеграция не может исходить из предположения, что каждый запрос выполняется ровно один раз. Соединение может оборваться после того, как внешняя система уже создала объект, ответ может не дойти до сайта, а очередь — повторно отправить ту же задачу после таймаута.
Если повторный запрос создаёт ещё один заказ, платёж, лид или контрагента, интеграция быстро начинает производить дубли. Для защиты от этого используют идемпотентность и стабильные внешние идентификаторы.
Что такое идемпотентный запрос
Идемпотентность означает, что повторное выполнение одной и той же операции не меняет итоговый результат после первого успешного выполнения. Например, повторная передача заказа с одним и тем же внешним ID должна обновить или вернуть существующий заказ, а не создать второй.
Почему нельзя полагаться только на название или email
Поля, которые человек может изменить, плохо подходят на роль технического ключа. Название компании меняется, email пользователя может быть общим, а номер заказа иногда формируется отдельно в каждой системе.
Надёжнее хранить постоянное соответствие идентификаторов: ID объекта сайта и ID объекта внешней системы. Такой подход особенно важен при интеграции сайта с CRM.
Что происходит при таймауте
Представим, что сайт отправил запрос на создание сделки. CRM создала её, но ответ не успел вернуться. Сайт видит ошибку соединения и повторяет запрос. Без ключа идемпотентности CRM создаст ещё одну сделку, хотя первая операция фактически прошла успешно.
Поэтому перед повтором важно понимать состояние операции. Если API поддерживает idempotency key, один и тот же ключ используют для всех попыток одной бизнес-операции.
Повторные попытки тоже должны иметь правила
- не повторять запрос бесконечно;
- разделять временные и постоянные ошибки;
- увеличивать интервал между попытками;
- фиксировать номер попытки и причину сбоя;
- после лимита переводить задачу в ошибочное состояние для ручного разбора.
Какие ошибки имеет смысл повторять
Временная недоступность сервиса, сетевой таймаут или HTTP 429 обычно могут быть поводом для повторной попытки. Ошибка валидации данных или отказ авторизации, наоборот, редко исчезнет сама. Повторять такой запрос без исправления причины бессмысленно.
Защита от дублей должна быть на нескольких уровнях
Стабильный внешний ID помогает сопоставить объекты. Идемпотентный ключ защищает конкретную операцию. Уникальные ограничения в базе не позволяют случайно создать два объекта с одним техническим идентификатором. Вместе эти механизмы значительно надёжнее, чем один условный поиск перед созданием.
Повторный запрос — нормальная часть интеграции. Дубль данных после повторного запроса — уже архитектурная проблема.
Практический чек-лист
- Определите постоянный идентификатор для каждого типа объектов.
- Храните связь ID между системами.
- Используйте idempotency key, если его поддерживает API.
- Разделите ошибки на повторяемые и неповторяемые.
- Добавьте ограниченное количество retry с увеличением паузы.
- Логируйте каждую попытку и финальный статус операции.
Если интеграция проектируется с нуля, сначала полезно определить направления обмена и владельца каждого типа данных. Это разобрано в статье о синхронизации данных сайта и 1С.