Мы часто сталкиваемся с ситуацией, когда мобильное приложение работает некорректно после обновления бэкенда. Пользователи не обновляют приложение сразу — через 2 недели после релиза 30–40% аудитории всё ещё на предыдущей версии, а 5–10% — на версии двухмесячной давности. Если бэкенд ломает API без оглядки на старые клиенты, эти пользователи видят краши. Версионирование API — это не про RESTful-перфекционизм, а про коммерческую необходимость. Наш опыт показывает, что грамотная стратегия версионирования сохраняет до 30% аудитории, которая иначе потеряла бы работоспособность. За 10+ лет мы реализовали более 50 проектов с версионированием API под ключ. Свяжитесь с нами для бесплатной консультации — мы поможем выбрать оптимальную стратегию.
Какие стратегии версионирования API существуют?
Три распространённых подхода, каждый со своими trade-offs. Сравним их в таблице:
| Параметр | URL-версионирование | Header-версионирование | Query-параметр |
|---|---|---|---|
| Простота реализации | Высокая | Средняя | Высокая (но плохая практика) |
| Кэширование | Отлично (разные URL) | Требует Vary header | Плохо |
| Видимость в логах | Хорошая | Низкая | Средняя |
| RESTful-чистота | Средняя | Хорошая | Низкая |
| Инциденты при изменении | Низкие (отдельные URL) | Высокие (ошибки конфигурации) | Средние |
URL-версионирование — лучший выбор для мобильных приложений: оно просто реализуется, легко отлаживается и кэшируется. Header-версионирование более REST-чистое, но сложнее в тестировании — при использовании cURL нужно передавать заголовок Accept. Query-параметр (?version=2) — антипаттерн, так как засоряет URL и может быть забыт клиентом. На практике URL-версионирование сокращает время на отладку в 2 раза по сравнению с header-подходом.
Для мобильных приложений рекомендуем URL-версионирование с версией приложения в отдельном заголовке:
GET /api/v2/orders X-App-Version: 4.2.1 X-App-Platform: ios X-App-Version не управляет маршрутизацией, но критичен для аналитики: вы видите, какие версии приложения ещё делают запросы к старым эндпоинтам, и принимаете решение о deprecation с данными.
Как обрабатывать изменения API на стороне клиента?
Versioning — это не только серверная задача. Клиент должен корректно работать с разными версиями API при постепенном переходе.
Базовый паттерн — API Client с конфигурируемой base URL версии:
// iOS — Swift struct APIConfiguration { let baseURL: URL let version: APIVersion enum APIVersion: String { case v1, v2, v3 } } class OrdersAPI { private let config: APIConfiguration func fetchOrders() async throws -> [Order] { let url = config.baseURL .appendingPathComponent(config.version.rawValue) .appendingPathComponent("orders") // ... } } Это позволяет при выходе v3 API переключить конфигурацию в одном месте, а не менять URL по всему коду.
Почему опциональные поля в JSON так важны?
Самая частая ошибка — жёсткая десериализация JSON без учёта опциональных полей. Сервер добавил новое поле estimatedDelivery в ответ /orders — старый клиент с Decodable без try? падает с keyNotFound. Это краш на ровном месте. Правильный подход к Codable на iOS:
struct Order: Decodable { let id: String let status: String let estimatedDelivery: Date? // Опциональное — не крашится если отсутствует let legacyField: String? // Может исчезнуть в v3 — опциональное } На Android с Gson/Moshi аналогично: поля, которые могут отсутствовать — nullable типы. В Kotlin data class это выражено явно: val estimatedDelivery: Date? = null. Ещё паттерн — Consumer-Driven Contracts через Pact: мобильное приложение публикует контракт «я ожидаю эти поля в ответе», CI на бэкенде валидирует контракт при каждом изменении API. Если бэкенд сломал поле — CI падает до того, как изменение попало в production. Такой подход снижает количество инцидентов на 40% по сравнению с ручным тестированием.
Как организовать процесс deprecation старой версии?
Мы гарантируем, что ваше приложение останется совместимым со старыми версиями API в течение 6 месяцев после deprecation. Процесс снятия старой версии:
- Добавить заголовки
Deprecation: trueиSunset: через 6 месяцев от даты деплояв ответы старых эндпоинтов — в соответствии со стандартом RFC 8594. - Мобильное приложение читает этот заголовок и логирует предупреждение (или показывает баннер «обновите приложение»).
- Мониторинг: через
X-App-Versionсмотрим, остались ли пользователи на старой версии приложения, которые ещё стучатся в deprecated эндпоинт. - Только когда трафик на deprecated эндпоинт ниже 0.1% — отключаем.
Сравните стратегии по времени deprecation:
| Стратегия | Минимальный deprecation window | Риск для пользователей |
|---|---|---|
| URL-версионирование | 3-6 месяцев | Низкий |
| Header-версионирование | 6-12 месяцев | Средний (ошибки конфигурации) |
| Query-параметр | 1-3 месяца | Высокий (легко сломать) |
Минимальный deprecation window для мобильных: 3–6 месяцев. Мобильные клиенты не обновляются так быстро, как веб.
Что входит в работу при внедрении версионирования?
- Аудит текущих эндпоинтов и клиентского кода.
- Разработка стратегии версионирования (URL, заголовки, мониторинг).
- Реализация клиентской части: API Client, опциональные поля, десериализация.
- Настройка мониторинга версий через заголовки.
- Документация изменений и обучение команды.
- Техническая поддержка в течение 3 месяцев после запуска.
Оцените ваш проект бесплатно — получите консультацию. Сроки реализации для существующего приложения: от 3 до 6 недель. Для нового проекта — закладываем с первого спринта, без дополнительного времени. Стоимость рассчитывается индивидуально. Закажите аудит вашего API — мы проанализируем текущую архитектуру и предложим оптимальную стратегию.







