Перейти к основному содержимому

Версионирование API: реальные примеры команд

· 8 мин. чтения
Artur Pan
CTO & Co-Founder at PanDev

Twilio поддерживает 14 активных версий API. Stripe фиксирует каждого клиента на версии, активной на момент регистрации, и держит версии аж с 2011 года. GitHub REST параллельно ведёт три major-версии и шлёт deprecation-заголовки за 12 месяцев до отключения. Ваша команда, скорее всего, пытается выжить с одной — и спорит, куда пихать версию: в URL, header или Accept.

Этот спор на самом деле — три разных решения, склеенных в один аргумент: где живёт версия, как скоупятся breaking changes и когда старые версии умирают. Правильный ответ на одно не спасёт, если два других кривые. Это плейбук на основе того, как реально работают компании с публичным API на скейле, плюс что мы видим внутри PanDev Metrics у клиентов с внутренними API на 20-200 потребителей.

{/* truncate */}

Проблема: стратегии версионирования, которую никто не записал

У большинства внутренних API нет «стратегии». Есть три геологических слоя истории:

  1. Оригинальные endpoints, написанные до того, как кто-то подумал про версии
  2. Префикс /v2/, добавленный после первого breaking change
  3. Header X-API-Version: 2026-01-15, появившийся после того, как кто-то прочитал блог Stripe

Клиенты бьются во все три одновременно. Новая SDK ломает мобильных клиентов на v1. Deprecation объявлен в Slack, но в OpenAPI-спеке этого нет. Команда тратит три спринта на распутывание.

Postman State of the API Report 2024 показывает: 58% разработчиков назвали breaking changes главной болью интеграции — выше, чем качество доков, rate limits и сложность auth. В API guidelines Microsoft (Brandon Werner, Mark Stafford) прямым текстом: «Breaking changes должны сопровождаться инкрементом версии». Команды, которые пропускают инкремент, шипят инциденты.

Decision flow для версионирования: новый endpoint, breaking или нет, major или extension, deprecation window, sunset Дебаты не про «какую схему версионирования взять», а про «что изменилось и кого это затронет». Схема — это сантехника; скоуп — это сложная часть.

Где живёт версия: три варианта, конкретные компромиссы

Версия в пути URL (/v1/users)

Используют: Twilio, GitLab, AWS (для большинства сервисов), Kubernetes

ПлюсыМинусы
Видно в логах и ошибкахСвязывает routing с версионированием
Легко роутить через load balancer / gatewayПровоцирует «big bang» major-версии
Не нужен tooling на клиентеЛомает REST-пуризм («у ресурса один URI»)
Дебажится curl-ом в одно действиеСложно делать per-field deprecation

Когда брать: внутренние API, B2B-платформы с небольшим числом major-версий, gateway-heavy архитектуры.

Версия в заголовке (Accept: application/vnd.api+json; version=3)

Используют: GitHub (до 2022), Atlassian, Azure

ПлюсыМинусы
URI стабильны и «REST-ovые»Не видно в браузере, дебажить сложнее
Fine-grained версионирование на каждый запросСложнее роутить на gateway
Поддерживает dual-shipping ответовКлиенты должны знать танец; SDK обычно это прячут

Когда брать: публичные API, где стабильность URL важна для SEO/закладок, или где нужно держать несколько версий на одном endpoint.

Date-based (Stripe-Version: 2024-06-20)

Используют: Stripe, Shopify (REST), часть Google API

ПлюсыМинусы
Клиент фиксируется на регистрации; никто не «решает» апгрейдитьсяНужна серьёзная инфраструктура совместимости на сервере
Мелкие breaking changes можно шипать еженедельно без фанфарСложно поднять, если вы не Stripe-масштаба
«Latest» становится opt-in, а не дефолтомСложнее объяснить, что поменялось между 2024-06-20 и 2024-07-10

Когда брать: SaaS-платформы с долго живущими интеграциями, где клиенту не хочется трогать работающий код. Требует серьёзных вложений в compat-слой — инженерный блог Stripe признаёт, что у них на это выделена отдельная команда.

GraphQL «без версий»

Используют: GitHub GraphQL, Shopify Storefront API, Meta

GraphQL-адепты утверждают, что версии — это антипаттерн: клиент выбирает поля, сервер помечает старые @deprecated, поля сосуществуют, пока кто-то их запрашивает. Работает для read-heavy API с умными клиентами. Не работает для mutations с меняющейся семантикой (например, авторизация платежей) — там нужны явные версии даже внутри GraphQL.

Как скоупятся breaking changes: вопрос, который большинство пропускают

Скоуп важнее схемы. Четыре класса изменений в порядке нарастания боли:

КлассПримерБампать версию?
Additive (новое опциональное поле / endpoint)Добавили customer.preferred_languageНет
Additive с новым обязательным inputНовый endpoint требует новый auth headerМинорно (soft)
Semantic (то же поле, другой смысл)amount стал post-tax вместо pre-taxMajor — всегда
Removal / rename поля или endpointУбрали user.legacy_idMajor — всегда

Первые два большинство делает правильно, последние два — криво. Semantic change без бампа версии — худший тип бага: ответ валидируется, парсится, сериализуется, но молча ломает математику downstream. Мы видели, как такое у клиента-ecommerce сломало финансовый отчёт на 3 недели — команда зашипила breaking semantic change как «minor bug fix».

Правило: если меняется семантика поля на сервере, это новое поле. Вводите amount_post_tax рядом с amount, помечаете amount deprecated, убираете после окна. Не «чините» amount на месте.

Deprecation window: математика, которая меняет решения

Про это спорит каждая API-команда. Реальные числа из публичных постмортемов:

КомпанияDeprecation windowСпособ оповещения
Stripe12+ месяцев (minor) / несколько лет (major)Email на аккаунт + dashboard + changelog
TwilioМинимум 12 месяцевChangelog + email + sunset header
GitHub RESTОбычно 18 месяцевDeprecation-заголовки + блог + docs warning
Atlassian CloudМинимум 6 месяцевDeprecation notice на endpoint + email клиентам
Google Maps PlatformОбычно 12 месяцевChangelog + deprecation header

Floor для платного B2B API в 2026 — 12 месяцев. Меньше — будут инциденты у клиентов; инциденты у клиентов — churn. Исключение — внутренний API с известными потребителями, где можно координироваться напрямую: окна 30-90 дней ок, если у вас есть Slack до каждой потребляющей команды.

Контринтуитивно: длина окна важна меньше, чем сигнал. Окно в 6 месяцев с Sunset: header, Deprecation: header, еженедельными напоминаниями и dashboard у клиента работает лучше, чем 12 месяцев, которых никто не замечает. RFC 8594 (Sunset HTTP Header) — ближайший стандарт; внедряйте его рано.

Шаблон политики для команды 10-100 инженеров

Это то, что мы рекомендуем клиентам, когда у внутренних API появляется >5 потребителей:

1. Схему выбираете один раз на API и записываете

  • Сервис-сервис внутри → версия в URL
  • Внешний SDK / клиентский API → date-based ИЛИ URL (одно из двух, не оба)
  • Публичный read-heavy граф → GraphQL с @deprecated

2. Политика breaking changes (стабильные правила)

  • Additive шипится в текущей версии
  • Rename / removal — новая версия И окно сосуществования
  • Semantic — новое поле, а не правка на месте

3. Коммуникация deprecation (обязательно для breaking)

  • Response header Deprecation: true
  • Sunset: Sat, 31 Dec 2026 23:59:59 GMT (формат RFC 8594)
  • Запись в changelog в момент анонса и в момент sunset
  • Dashboard-метрика: вызовы к deprecated-версиям по клиенту

4. Процесс sunset (автоматизация, не тикеты)

  • Feature flag, который возвращает 410 Gone после sunset-даты
  • Вызовы до sunset логируются в выделенный канал
  • Customer-success на T-90 и T-30 дней

Типовые ошибки

  • Анонс в блоге, который никто не читает. Deprecation живёт в ответе API, а не в контент-маркетинге. Если ответ не кричит «я уйду», инженерные команды узнают в день отключения.
  • Версионировать всё подряд. Rename одного внутреннего endpoint — не повод делать v2-всего. Версия скоупится на namespace.
  • 5+ активных major-версий. Twilio это вывозит, но инвестиции у них такие, что большинство команд не потянут. Три активные major — практический потолок для команды в 20 человек.
  • Тихие breaking changes под видом bug fix. «Мы починили расчёт налога» — поздравляем, вы только что выпустили major без migration path.
  • Версия одновременно в URL И в header. Выбирайте одно. Два — неоднозначно, клиенты будут спорить, кто побеждает.

Как измерять, что версионирование работает

Три реально полезные метрики:

МетрикаЗдоровоВниманиеПлохо
% запросов на последней версии>70%40-70%<40%
Ср. возраст (дни) самой используемой версии<180180-365>365
Инциденты из-за непрокоммуницированных breaking changes0/квартал1-2/квартал3+/квартал

PanDev Metrics не видит объёмы ваших API-запросов напрямую — наш датасет это IDE + Git, не gateway-логи. Зато мы видим, как version bumps превращаются в инженерную работу: время на поддержку backward-compat слоя, lead time между «deprecated» и «removed» коммитами, сколько раз PR с версией отбивается от ревью. У команд с чёткой политикой версионирования lead time на API-change PR на 30-40% короче, чем у команд, которые спорят о схеме прямо в ревью. Это перекликается с исследованиями DORA — ясность процесса сокращает cycle time сильнее, чем сырая скорость.

Связка с code review прямая: ревьюеры, знающие политику, не спорят; они её применяют. Ревьюеры, не знающие политики, пишут комменты на 400 слов, чтобы её выработать.

Честный лимит

Наша сила — IDE-телеметрия; мы не видим gateways и клиентские интеграции. Цифры по deprecation window — из публичных инженерных блогов и RFC 8594, не из нашей телеметрии. Зато мы коррелируем инженерные усилия с API-change коммитами, и паттерн ясный: команды с записанной политикой тратят вдвое меньше времени на API-change PR.

Ещё честность: если вы 5 человек, делаете greenfield внутренний API с 2 потребителями — пропустите большинство этого. URL-версионирование, бампайте, когда надо, и не стройте фреймворк для проблемы, которой у вас пока нет. Цена преждевременной инфраструктуры реальна.

Самый жёсткий тезис

Спор о схеме версионирования — это прокси для настоящего спора: «есть ли у нас политика breaking changes?» Команды без политики будут часами спорить URL-vs-header и всё равно зашипят breaking changes без бампа. Команды с политикой год проживут на одной схеме и поймут, что схема-то и не решала. Напишите политику раньше, чем выбираете сантехнику.

По теме

Готовы увидеть метрики своей команды?

30-минутная персональная демонстрация. Покажем как PanDev Metrics решает задачи именно вашей команды.

Забронировать демо