API ломает старых клиентов не только при удалении endpoint. Достаточно переименовать поле, изменить тип, сделать nullable обязательным, поменять смысл статуса или порядок пагинации. Восстановление начинается с точного контракта прежнего клиента, а не с возврата всего сервиса к старому коду.

Определите первую несовместимую разницу между старым запросом/ответом и новой реализацией. Временно восстановите совместимость адаптером или отдельной версией, затем объявите срок миграции и наблюдайте использование старого контракта.

Что проверить в первую очередь

Начните с воспроизводимого сценария: зафиксируйте время сбоя, идентификатор объекта, версию приложения или конфигурации и последнее известное рабочее состояние. Не меняйте несколько параметров одновременно. Один контролируемый шаг должен подтверждать или исключать одну гипотезу, иначе временное исчезновение симптома легко принять за исправление. Перед работой с данными и настройками подготовьте резервную копию и понятный способ отката.

  • Сохраните пример запроса и ответа работающей и сломанной версии.
  • Проверьте типы, обязательность, enum, формат дат, коды ошибок и пагинацию.
  • Определите версии приложений и интеграций, которые еще используют старый контракт.
  • Посмотрите дату релиза и конкретный commit схемы или serializer.

Почему возникает проблема

Внешний симптом часто появляется не в том компоненте, где возникла первичная ошибка. Интерфейс может показывать неверное состояние из-за backend, очереди, кеша, прав доступа или внешнего API. Полезно проследить данные от источника до результата и найти первую точку расхождения. Это надежнее, чем исправлять последнее сообщение об ошибке или бесконечно перезапускать сервис.

  • Поле удалили или переименовали без периода совместимости.
  • Число стало строкой, null запретили или добавили новый обязательный enum.
  • Сортировка и cursor pagination изменили состав страниц.
  • Ошибка получила другой HTTP-код, и клиент больше не запускает retry.
  • Gateway направляет старый URL на новую реализацию без adapter.

Пошаговая диагностика

Диагностику проводите на тестовой записи или отдельном окружении. В журналах скрывайте токены, пароли, персональные данные и содержимое документов. Для каждого шага сохраняйте измеримый результат: код ответа, версию записи, идентификатор события, состояние процесса, контрольную сумму или время выполнения. Сравнение одной и той же операции до и после изменения помогает отделить причину от совпадения.

  • Сравните OpenAPI schemas и реальные payload на границе сервиса.
  • Воспроизведите запрос старой версией SDK или сохраненным контрактным тестом.
  • Проверьте access log по User-Agent, API key и version header.
  • Отделите транспортную ошибку от изменения бизнес-смысла поля.
  • Найдите потребителей, о которых нет записи в документации.

Что считается обратно совместимым изменением

Даже добавление поля может быть несовместимым, если строгий клиент запрещает неизвестные свойства. Совместимость оценивают по реальному поведению потребителей, а не только по серверной схеме.

  • Добавление optional-поля обычно безопасно для tolerant readers.
  • Удаление, переименование и смена типа почти всегда требуют новой версии.
  • Расширение enum ломает клиентов с exhaustive switch.
  • Изменение порядка, единиц измерения или часового пояса меняет смысл без изменения JSON schema.
  • Новые rate limits и коды ошибок также являются частью контракта.

Как исправить проблему

Разбейте исправление на небольшие обратимые изменения. Сначала устраните подтвержденную причину, затем повторите исходный сценарий и проверьте соседние функции. Массовое обновление данных запускайте на ограниченной выборке с отчетом и только после сверки расширяйте на весь объем. Не отключайте авторизацию, валидацию, шифрование или проверку сертификатов ради быстрого исчезновения ошибки.

  • Верните adapter для старого формата либо отдельный /v1 на период миграции.
  • Зафиксируйте OpenAPI и генерируйте diff несовместимых изменений в CI.
  • Добавьте consumer-driven contract tests для критических клиентов.
  • Опубликуйте migration guide с примерами и датой отключения старой версии.
  • Собирайте метрику использования deprecated endpoint до его удаления.

Безопасный порядок внедрения

  • Сохраните затрагиваемые данные, конфигурацию и текущие журналы, заранее проверив реальный способ восстановления.
  • Повторите проблему на тестовом объекте без реальных списаний, рассылок и необратимых изменений клиентских данных.
  • Зафиксируйте изменение в системе контроля версий или журнале работ вместе с причиной и планом отката.
  • Проведите тест на нормальном сценарии, ошибочном вводе, повторном запросе, параллельной операции и временной недоступности зависимости.
  • После выпуска наблюдайте логи, метрики и полный пользовательский путь, а не только один успешный запрос.

Как проверить результат

Разовый успешный тест недостаточен. Повторите операцию, проверьте крайние значения, одновременные действия и восстановление после перезапуска или временного сбоя. Для важного сценария сохраните автоматический тест либо короткий регрессионный чек-лист. Итог должен подтверждаться не только интерфейсом, но и состоянием базы, очереди, внешнего сервиса и журналом действий.

  • Старый клиент снова выполняет ключевые операции без изменения своей версии.
  • Новый клиент получает новый контракт и не зависит от adapter.
  • Повторные запросы и ошибки сохраняют ожидаемую семантику.
  • Метрика показывает всех оставшихся потребителей старой версии.

Типичные ошибки при исправлении

  • Считать внутреннего клиента единственным потребителем API.
  • Менять только OpenAPI, оставляя другой фактический ответ.
  • Возвращать HTTP 200 с ошибкой внутри тела ради совместимости.
  • Отключать старую версию по календарю без метрики реального использования.

Как предотвратить повторение

Профилактика строится вокруг явных контрактов, повторяемых релизов и наблюдаемости. Система должна не только работать сейчас, но и позволять быстро увидеть нарушение правила при следующем обновлении, росте нагрузки или сбое внешнего сервиса. Проверки полезно автоматизировать там, где ошибка уже привела к потерям времени, данных или заявок.

  • Запрещайте breaking changes автоматическим schema diff.
  • Храните контрактные примеры и тесты от имени потребителей.
  • Назначайте владельца версии и понятную политику deprecation.
  • Логируйте версию клиента и endpoint без чувствительных payload.

Что подготовить для технического разбора

  • Описание ожидаемого и фактического поведения с точной последовательностью действий.
  • Время проблемы, идентификатор тестового объекта и версии затронутых компонентов.
  • Фрагменты журналов до и после ошибки без секретов и персональных данных.
  • Перечень последних изменений и уже выполненных проверок.
  • Безопасный доступ к тестовой среде либо способ воспроизвести сбой без влияния на клиентов.

Частые вопросы

Где лучше указывать версию: URL или заголовок?

Оба варианта работают. Важнее единая политика, маршрутизация, документация и независимый жизненный цикл версий.

Можно ли никогда не удалять v1?

Технически можно, но стоимость поддержки растет. Безопаснее измерить использование, помочь миграции и отключить версию по прозрачной процедуре.

Когда нужна помощь специалиста

Если обновление API сломало приложения или интеграции, я могу найти несовместимое изменение, восстановить adapter или версию, добавить contract tests и подготовить контролируемую миграцию клиентов.