Совместимость API и обновления
1) Базовые принципы совместимости
Additive-first: добавляйте новое, не ломая старое (новые опциональные поля/эндпоинты, новые enum-значения).
Стабильные контракты: «что обещано в спецификации — то и работает»; поведение документировано.
Backward > Forward: приоритет обратной совместимости; forward допускается через tolerant-readers.
Документы первичны: единственный источник правды — версия схемы в registry (OpenAPI/AsyncAPI/Proto).
Явная эволюция: breaking — только через новую major-версию и миграционный гид.
2) Таксономия изменений
2.1 Совместимые (MINOR/PATCH)
Добавление опциональных полей/хедеров, новых эндпоинтов, query-параметров с дефолтами.
Увеличение лимитов (`page_size`, TTL), уточнение ошибок без смены кодов/семантики.
Добавление значений enum, если клиенты игнорируют «незнакомые» (tolerant-reader).
2.2 Неоднозначные (Behavioral)
Изменение дефолтов, порядка сортировки, тонких таймаутов, квот — может «ломать» бизнес-логику. Требует RFC + анонс и канареек.
2.3 Ломающие (MAJOR)
Переименование/удаление полей, изменение типа/формата, замена кодов ошибок, обратная несовместимость контрактов/схем аутентификации.
3) Политика версионирования
Стратегия: `path versioning` (`/v1`, `/v2`).
Минор/патч: «добавляй, не ломай».
Датированные заголовки (доп.): `X-API-Version-Date` для мягких постепенных изменений.
Медиа-типы (опц.): `Accept: application/vnd.acme.v1+json` для тонкой грануляции.
4) Депрекации и sunset
4.1 Коммуникационные заголовки
Deprecation: true
Sunset: 2026-03-31T00:00:00Z
Link: </guides/reports-v2>; rel="successor-version"
4.2 Порядок вывода
1. Анонс в портале/рассылке/SDK release notes.
2. Окно предупреждения ≥ 90–180 дней.
3. Статусы в дашборде adoption.
4. После sunset — 410 Gone или «read-only» режим на период grace, если согласовано.
5) Миграции и совместное сосуществование версий
Dual-write/dual-read в переходный период и сверка отчетами.
Адаптеры (временные): gateway-преобразования старых payload → новые схемы; срок жизни адаптера ограничен.
SDK-помощь: релизы, поддерживающие обе версии, с предупреждениями депрекации (1 раз за процесс).
Фича-флаги: включение новой семантики по списку ключей/тенантов.
6) Backward и forward совместимость
6.1 Backward (старые клиенты ↔ новый сервер)
Не менять форматы типов/обязательность.
Новые поля — только опциональные.
Ошибки — прежние `error_code`, новые коды добавлять, не заменять.
6.2 Forward (новые клиенты ↔ старый сервер)
Проверять наличие возможностей (capabilities) через `OPTIONS`/`/versions`.
Грейс-поведение: клиент должен терпимо относиться к отсутствующим фичам.
7) Контракты и автоматические проверки
Registry: храним версии схем; PR-дифы → отчеты «breaking / non-breaking».
Линтер: имена/типы, идемпотентность, пагинация, стабильные коды.
CDC (Consumer-Driven Contracts): тесты интеграторов в CI поставщика (Pact и аналоги).
Гейт: PR блокируется при breaking без `major bump`/RFC.
yaml
- name: API Diff run: api-diff --from main --to $PR_SHA --fail-on=breaking --format junit --out diff. xml
8) Канареечный выпуск и обратный ход
Canary: 10% → 25% → 50% → 100% трафика; авто-откат при ухудшении SLO (5xx/latency/429).
Бета-ключи: доступ новым версиям по allowlist.
Release freeze: при сгорании error-budget.
Аналитика принятия: доля трафика/клиентов на новой версии, время миграции.
9) Совместимость в деталях: ошибки, пагинация, идемпотентность
9.1 Ошибки
Не менять HTTP-статусы в существующих сценариях.
`error_code` — стабильный; новые коды только добавлять.
`application/problem+json` — единый формат.
9.2 Пагинация
Переход на cursor/keyset = MINOR, если поддержан старый `offset/limit`.
Документируйте сортировку `(updated_at,id)` и стабильность курсора.
9.3 Idempotency
Для write — `Idempotency-Key` + `409 IDEMP_REPLAY` при конфликте.
Миграции не должны менять семантику идемпотентности.
10) Gateway-трансформации (когда уместно)
Map v1→v2 полей, нормализовать ошибки, конвертировать форматы дат/денег.
Guardrails: трансформации прозрачны и логируются; не прячьте breaking, а используйте как мост с ограниченным сроком.
11) Коммуникации и портал
Changelog с датами (`added/changed/deprecated/removed/fixed`).
Карточка версии: статус (beta/GA/deprecated), дата sunset, ссылки на гайды.
Вебхуки уведомлений: `deprecation.notice`, `version.released`, `plan.change`.
SDK release notes + баннер в портале.
12) Метрики успеха
Adoption rate v2 (по запросам/клиентам).
Backward-compat incidents (кол-во «ломок»).
Error mix (доли 4xx/5xx/429) до/после релиза.
Time-to-Adopt медиана.
Support load (тикеты/нед).
Cost-to-Serve (инфраструктурная стоимость на вызов).
13) Шаблоны и примеры
13.1 Заголовки версий и депрекаций
X-API-Version: v1
Deprecation: true
Sunset: 2026-03-31T00:00:00Z
Link: </v2/reports>; rel="successor-version"
13.2 Политика версий (фрагмент YAML)
yaml versioning:
strategy: "path"
compatibility:
minor: "additive-only"
patch: "bugfix/perf, no schema change"
deprecation:
min_notice_days: 120 rollout:
canary_steps: [10,25,50,100]
rollback_checks: ["5xx_rate","p95_latency","429_rate","adoption"]
13.3 OpenAPI: совместимое добавление поля
yaml components:
schemas:
Report:
type: object required: [id, createdAt]
properties:
id: { type: string }
createdAt: { type: string, format: date-time }
cursor: { type: string, description: "optional for v1. 2+" } # additive
14) Чек-лист релиза (MINOR/MAJOR)
MINOR
- DIFF: non-breaking, линтер зеленый
- Документация/SDK обновлены (примеры/кодеки)
- Канарейка + авто-откат по SLO
- Комм-план, страница в портале
- Дашборды adoption и ошибок
MAJOR
- RFC/ADR, дата sunset и окно ≥90–180 дней
- v1↔v2 мост (gateway) и миграционный гид
- Dual-write/read и сверки
- SDK с обоими API + предупреждения
- Пилот с ключевыми интеграторами
15) План внедрения (3 итерации)
1. Фундамент (2 недели):
Registry схем, линт и auto-diff в CI; политика совместимости; заголовки `Deprecation/Sunset`.
2. Управляемые релизы (3–4 недели):
Канарейки, фича-флаги, SLO-алерты; портал версий; SDK-релизы с поддержкой 2 веток.
3. Автоматизация и масштаб (непрерывно):
CDC-тесты потребителей в CI, прогноз sunset по трендам adoption, автоматические нотификации и напоминания.
16) Мини-FAQ
Можно ли менять тип поля без major?
Нет. Даже «строка→число» — breaking. Введите новое поле, старое — deprecate.
Enum: можно добавлять значения?
Да, если клиенты — tolerant-readers. Иначе — сначала оповещение и бета.
Сколько держать старую версию?
Пока adoption новой ≥95% и выдержано окно депрекации. Фиксируйте срок в политике.
Итог
Совместимость API — это дисциплина: additive-подход, формальные схемы и дифы, канареечные релизы, ясные депрекации и управляемые миграции. Закрепите политику изменений, автоматизируйте проверки и коммуникации, меряйте adoption — и ваши обновления перестанут ломать клиентов, а скорость эволюции вырастет без потери надежности.