Команда внедрила idempotency key для защиты от дублей заказов при ретраях клиента. Логика простая: перед вставкой заказа проверяем, есть ли запись с таким ключом в таблице, если нет — вставляем.
Optional existing = orderRepository.findByIdempotencyKey(key); if (existing.isEmpty()) { orderRepository.save(new Order(key, data)); }
Проблема в окне между findByIdempotencyKey и save. Если клиент делает ретрай быстро — например, из-за таймаута на своей стороне, пока сервер ещё обрабатывает первый запрос — второй поток проходит проверку isEmpty() до того, как первый успел сохранить запись. Оба потока видят пустой результат и оба вставляют заказ.
Это не ORM-баг и не баг конкретного фреймворка — это классический race condition между чтением и записью без атомарной гарантии на уровне БД.
Правильное решение — не проверка в коде приложения, а уникальный constraint на колонке idempotency_key в БД и обработка исключения о нарушении constraint как сигнала "запись уже существует". На собесе здесь часто ждут слово upsert или ON CONFLICT DO NOTHING в Postgres — атомарная операция вместо связки из двух независимых запросов.
Idempotency key защищает от дублей только если уникальность проверяет СУБД, а не приложение двумя отдельными запросами.
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки