Deploy vs Release: Почему Progressive Delivery разделяет то, что вы считали одним и тем же

Ваша команда только что закончила новый поток оформления заказа. Код протестирован, пул-реквест смержен, пайплайн деплоя зелёный. Вы нажимаете «Задеплоить». Новая версия уходит в продакшен. Теперь каждый пользователь видит переработанную кнопку, переставленные поля формы и новый экран подтверждения.

Но что, если вы хотели бы сначала посмотреть, как новый поток работает, прежде чем показывать его всем? Что, если вы хотели бы дать попробовать его только 5% пользователей, а затем расширять на основе реальных данных?

В большинстве команд деплой и релиз происходят одновременно. Когда новый код попадает на сервер, фичи внутри него становятся доступны пользователям. Но эти два действия не обязательно должны быть связаны. Разделение даёт вам уровень контроля, который меняет ваше представление о поставке софта.

Деплой — техническая операция. Релиз — пользовательский опыт.

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

Релиз — это действие, делающее фичу доступной пользователям. Это решение, основанное на опыте. Код уже выполняется на сервере, но фича скрыта за переключателем. Когда вы переключаете этот тумблер, пользователи видят новое поведение.

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

Диаграмма ниже иллюстрирует разделение:

flowchart TD A[Код смержен] --> B[Деплой на сервер] B --> C[Весь код выполняется на сервере] C --> D{Проверка feature flag} D -- Флаг включён --> E[Релиз фичи пользователям] D -- Флаг выключен --> F[Фича скрыта от пользователей] E --> G[Мониторинг метрик] G --> H{Данные положительные?} H -- Да --> I[Расширить процент раскатки] H -- Нет --> J[Выключить флаг] I --> K[Полный релиз] K --> L[Удалить флаг из кода] J --> F

Это разделение — основа progressive delivery.

Конкретный пример

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

С progressive delivery вы действуете так:

  1. Вы деплоите новую версию в продакшен. Код новой кнопки выполняется на сервере, но скрыт. Пользователи видят старую кнопку.
  2. Вы настраиваете систему feature flags так, чтобы показывать новую кнопку 5% пользователей. Эти пользователи выбираются случайно.
  3. Через неделю вы проверяете данные. Пользователи, видевшие новую кнопку, совершали покупки чаще. Путаницы не зафиксировано.
  4. Вы увеличиваете раскатку до 50% пользователей. Проходит ещё неделя. Данные всё ещё хорошие.
  5. Вы релизите фичу на 100% пользователей. Теперь она полностью активна.

Обратите внимание: один деплой, несколько релизов. Код попал в продакшен один раз. Фича становилась видимой поэтапно, на основе реального поведения пользователей.

Feature flags — механизм разделения

Чтобы разделить деплой и релиз, нужны feature flags. Feature flag — это условная ветка в вашем коде, которая проверяет, должна ли фича быть активна для текущего пользователя. Флаг управляется извне, обычно через конфигурационный сервис или специальную платформу для фича-флагов.

Простой feature flag в коде выглядит так:

if feature_flags.is_active("new_checkout_button", user_id):
    render_new_button()
else:
    render_old_button()

Флаг можно переключить без нового деплоя. Вы меняете конфигурацию, и следующий запрос от этого пользователя увидит новое поведение. Никаких изменений кода, сборки или деплоя.

Feature flags также позволяют проводить эксперименты. Вы можете запускать A/B-тесты, направляя разные сегменты пользователей на разные варианты фичи. Одна группа видит красную кнопку, другая — синюю. Данные подскажут, какая работает лучше.

Чем это отличается от canary и staged rollout

Canary-деплой и staged rollout направляют пользователей на разные версии приложения. Вы запускаете две версии рядом, и балансировщик нагрузки отправляет процент трафика на новую версию. Если что-то пошло не так, вы перенаправляете трафик обратно на старую версию.

Progressive delivery работает иначе. Вы запускаете одну версию приложения. Все пользователи попадают на одни и те же серверы. Но внутри этой версии разные пользователи видят разные фичи. Разделение происходит на уровне фич, а не на уровне приложения.

Это различие важно, когда вы хотите релизить фичу независимо от других изменений в том же деплое. С canary вы не можете релизить новую кнопку для 5% пользователей, оставляя остальную часть новой версии скрытой. Вы либо отправляете пользователей на новую версию, либо на старую. С progressive delivery вы управляете каждой фичей индивидуально.

Цена feature flags

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

Распространённый паттерн — использовать флаг для фичи, подтвердить её, раскатить полностью, а затем удалить флаг в следующем спринте. Но команды часто забывают об этом шаге. Флаг остаётся в коде, и никто не помнит, что он контролирует и активен ли он ещё.

Здесь важна дисциплина. Относитесь к feature flags как к временным по умолчанию. Когда фича полностью выпущена для всех пользователей, запланируйте работу по очистке. Если вы используете платформу для фича-флагов, большинство инструментов предоставляют дашборды, показывающие, какие флаги полностью раскатаны и готовы к удалению.

Когда progressive delivery имеет смысл

Progressive delivery нужен не каждой команде. Если ваше приложение небольшое, пользовательская база однородна, а фичи просты, накладные расходы на feature flags могут не окупиться.

Но progressive delivery становится ценным, когда:

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

Ключевая идея в том, что progressive delivery даёт вам золотую середину между «поставить всем» и «не ставить вообще». Вы можете задеплоить код, наблюдать за эффектом и расширять релиз на основе фактов.

Практический чеклист для внедрения progressive delivery

Если вы решили разделить деплой и релиз, вот шаги для начала:

  • Выберите одну фичу, которая выиграет от постепенного показа. Не начинайте со всех фич сразу.
  • Добавьте feature flag для этой фичи. Используйте простой конфигурационный файл или выделенный сервис.
  • Задеплойте код с выключенным флагом. Убедитесь, что фича скрыта.
  • Включите флаг для небольшого процента пользователей. Мониторьте метрики и логи.
  • Расширяйте процент на основе данных. Если что-то пошло не так, выключите флаг немедленно.
  • Когда фича полностью раскатана, удалите флаг из кода.

Вывод

Деплой и релиз — не одно и то же. Деплой — это размещение кода на серверах. Релиз — это делание фич видимыми для пользователей. Progressive delivery разделяет эти два действия, чтобы вы могли поставлять код по своему графику, а релизить фичи — по графику данных.

В следующий раз, когда ваша команда закончит фичу, спросите: нужно ли релизить это всем прямо сейчас, или можно позволить данным решить?