Версионирование API
Введение: обновление навигатора 🧭
Представьте навигатор в машине: вы обновляете карты, но водитель всё равно должен доехать по старым маршрутам.
API живёт так же — оно меняется, но клиенты не могут «сломаться» от обновления.
API живёт так же — оно меняется, но клиенты не могут «сломаться» от обновления.
💡 Совет: версия — это обещание: что именно вернёт сервер.
✅ Вывод: версионирование защищает клиентов от неожиданных изменений.
✅ Вывод: версионирование защищает клиентов от неожиданных изменений.
Проблема → решение
Проблема: без версий любое изменение ломает старые приложения.
Решение: вводим версии и правила, как менять API безопасно.
Решение: вводим версии и правила, как менять API безопасно.
✅ Вывод: версия = безопасная эволюция API.
Ключевые термины (простыми словами)
- Versioning (версионирование) — управление изменениями API через версии.
- Breaking change (ломающее изменение) — изменение, которое ломает старых клиентов.
- Backward compatibility (обратная совместимость) — старый клиент продолжает работать.
- Deprecation (устаревание) — версия ещё работает, но будет отключена.
- Sunset (срок отключения) — дата, после которой версия будет выключена.
- Semantic Versioning (семантическое версионирование) — формат Major.Minor.Patch.
Самое важное (must‑know)
- Breaking change = новая major‑версия.
- Нельзя тихо менять поведение v1.
- Депрекация всегда с предупреждением и сроком.
- Минимум две версии в поддержке, если есть живые клиенты.
- Единый способ версии во всём API.
✅ Вывод: эти правила защищают бизнес от массовых сбоев.
Как обычно переводят клиентов на новую версию
Простыми словами: сначала дают попробовать v2, потом постепенно переводят всех, и только после срока отключают v1.
Аналогия: открывают новую кассу рядом со старой и проверяют, что очередь идёт без сбоев.
Как это выглядит на практике:
- Запускают v2 параллельно с v1.
- Дают доступ тестовой группе или 10% трафика.
- Если всё стабильно — расширяют охват.
- Объявляют Deprecation и Sunset для v1.
- После дедлайна v1 выключают.
✅ Вывод: переход всегда постепенный, а выключение v1 — только после дедлайна.
1. Версия API — это контракт
Назначение: фиксировать ожидания клиента.
Простыми словами: клиент знает, что именно вернётся в ответе.
Аналогия: меню в кафе — если заказал «латте», ты всегда получишь латте.
Простыми словами: клиент знает, что именно вернётся в ответе.
Аналогия: меню в кафе — если заказал «латте», ты всегда получишь латте.
Пример:
/api/v1/courses/api/v2/courses🔎 Как это происходит на практике:
- Мобильное приложение вызывает /api/v1/courses.
- Сервер возвращает ответ в формате v1.
- Старый клиент работает без обновления.
Характеристики:
- ✅ версия = обещание формата;
- ✅ клиент сам выбирает версию;
- ✅ разные версии могут жить параллельно.
Когда использовать: всегда, когда API развивается.
✅ Вывод: версия = договор между сервером и клиентом.
✅ Вывод: версия = договор между сервером и клиентом.
2. Версия в URL (path)
Назначение: явно показывать версию в пути.
Простыми словами: сразу видно, какую версию вы вызываете.
Аналогия: как номер этажа на кнопке лифта.
Простыми словами: сразу видно, какую версию вы вызываете.
Аналогия: как номер этажа на кнопке лифта.
Пример:
GET /api/v1/coursesGET /api/v2/courses🔎 Как это происходит на практике:
- Бэкенд публикует /api/v2/courses параллельно с v1.
- В логах видно, какую версию вызывает клиент.
- QA проверяет обе версии отдельно.
Характеристики:
- ✅ просто читать и логировать;
- ✅ удобно для роутинга;
- ✅ легко объяснить новичкам.
Когда использовать: когда нужно максимум прозрачности.
✅ Вывод: путь = самый понятный способ версии.
✅ Вывод: путь = самый понятный способ версии.
3. Версия в заголовках
Назначение: хранить версию отдельно от URL.
Простыми словами: адрес остаётся чистым, версия уходит в заголовок.
Аналогия: как пропуск на входе — адрес тот же, доступ разный.
Простыми словами: адрес остаётся чистым, версия уходит в заголовок.
Аналогия: как пропуск на входе — адрес тот же, доступ разный.
Пример:
GET /coursesAccept: application/json; version=2X-API-Version: 2🔎 Как это происходит на практике:
- Клиент шлёт заголовок X-API-Version: 2.
- Сервер маршрутизирует запрос на v2.
- Без заголовка клиент остаётся на версии по умолчанию.
Характеристики:
- ✅ URL не меняется;
- ✅ удобно для content negotiation;
- ⚠️ сложнее дебажить без заголовков.
Когда использовать: когда важно сохранить короткие URL.
✅ Вывод: заголовки дают гибкость, но требуют дисциплины.
✅ Вывод: заголовки дают гибкость, но требуют дисциплины.
4. Breaking vs non‑breaking изменения
Назначение: понимать, когда нужна новая версия.
Простыми словами: ломающее = меняет ожидания клиента.
Аналогия: как замена ключа у двери — старый больше не подходит.
Простыми словами: ломающее = меняет ожидания клиента.
Аналогия: как замена ключа у двери — старый больше не подходит.
Пример:
Breaking: удалили поле priceNon‑breaking: добавили поле discount🔎 Как это происходит на практике:
- Команда удаляет поле price — это breaking.
- Решение: выпуск v2 с новым форматом.
- Добавление нового поля остаётся в v1.
Характеристики:
- ✅ breaking = новая major;
- ✅ non‑breaking = можно оставить версию;
- ✅ удаление/переименование почти всегда breaking.
Когда использовать: при планировании релизов.
✅ Вывод: правильная классификация защищает клиентов.
✅ Вывод: правильная классификация защищает клиентов.
5. Депрекация и Sunset‑политика
Назначение: безопасно выключать старые версии.
Простыми словами: предупреждаем заранее, когда версия перестанет работать.
Аналогия: как объявление «станция будет закрыта через месяц».
Простыми словами: предупреждаем заранее, когда версия перестанет работать.
Аналогия: как объявление «станция будет закрыта через месяц».
Пример:
Deprecation: trueSunset: 2025-12-01🔎 Как это происходит на практике:
- В ответах v1 появляется Deprecation: true.
- Клиенты видят Sunset и планируют переход.
- После даты v1 отключается.
Характеристики:
- ✅ объявление срока заранее;
- ✅ миграционный период;
- ✅ коммуникация с клиентами.
Когда использовать: при выводе v1/v2 из поддержки.
✅ Вывод: депрекация = уважение к клиентам.
✅ Вывод: депрекация = уважение к клиентам.
6. Документация и коммуникация
Назначение: объяснить, что изменилось и как перейти.
Простыми словами: клиент должен знать, что делать дальше.
Аналогия: инструкция к обновлению телефона.
Простыми словами: клиент должен знать, что делать дальше.
Аналогия: инструкция к обновлению телефона.
Пример:
Changelog:- v2: поменяли формат датыMigration guide:- замените поле createdAt на created_at🔎 Как это происходит на практике:
- Команда публикует changelog и migration guide.
- Фронтенд меняет поле createdAt → created_at.
- После релиза v2 клиенты переходят без сбоев.
Характеристики:
- ✅ release notes;
- ✅ guide по миграции;
- ✅ единая версия в документации.
Когда использовать: при каждом релизе новой версии.
✅ Вывод: без документации версия не работает в реальности.
✅ Вывод: без документации версия не работает в реальности.
Сравнение: URL vs Header vs Query
| Подход | Пример | Плюсы | Минусы |
|---|---|---|---|
| URL path | /api/v1/courses | прозрачно, легко логировать | длиннее URL |
| Header | X-API-Version: 2 | чистый URL, гибко | сложнее дебажить |
| Query | ?version=2 | быстро подключить | легко перепутать и забыть |
✅ Вывод: чаще всего выбирают URL или заголовки.
Часто спрашивают на собеседованиях
- Что такое breaking change? удаление/переименование полей или изменение смысла ответа.
- Нужно ли версионировать всегда? да, если API публичное или используется мобильными клиентами.
- URL vs Header — что выбрать? URL проще для команд и логов, Header гибче.
- Сколько версий держать? минимум две, если клиенты ещё живые.
- Как правильно отключать v1? через Deprecation и Sunset с сроком.
✅ Вывод: эти ответы — классика на интервью.
Типичные ошибки
Ошибка 1: меняют v1 без новой версии
❌ Тихо меняют формат ответа.
✅ Публикуют v2 и оставляют v1.
Почему: старые клиенты иначе ломаются.
✅ Публикуют v2 и оставляют v1.
Почему: старые клиенты иначе ломаются.
Ошибка 2: смешивают способы версии
❌ Где‑то v1 в URL, где‑то в header.
✅ Один способ во всём API.
Почему: единые правила снижают ошибки.
✅ Один способ во всём API.
Почему: единые правила снижают ошибки.
Ошибка 3: не дают срок отключения
❌ «Когда‑нибудь выключим v1».
✅ Указывают дату Sunset.
Почему: клиентам нужен дедлайн.
✅ Указывают дату Sunset.
Почему: клиентам нужен дедлайн.
Ошибка 4: считают добавление поля breaking
❌ Новое необязательное поле = новая версия.
✅ Оставляют ту же версию.
Почему: backward‑compatible изменения не ломают клиентов.
✅ Оставляют ту же версию.
Почему: backward‑compatible изменения не ломают клиентов.
Ошибка 5: нет миграционной инструкции
❌ Клиент сам «догадается».
✅ Дают migration guide.
Почему: снижает ошибки при переходе.
✅ Дают migration guide.
Почему: снижает ошибки при переходе.
Best Practices
- Выберите один способ версии и соблюдайте его.
- Breaking изменения — только через новую major‑версию.
- Всегда публикуйте сроки депрекации.
- Держите минимум две версии в поддержке.
- Документируйте изменения и давайте migration guide.
Заключение
Версионирование — это не «бюрократия», а защита пользователей.
Правила версий позволяют развивать API без хаоса.
Правила версий позволяют развивать API без хаоса.
✅ Вывод: версионирование = устойчивость бизнеса и спокойствие клиентов.