Почему архитектура super app ломается на втором релизе
Первая версия super app собирается быстро: единый репозиторий, общие модули авторизации, платежей и профиля, один слой данных. Пока команд две-три, это ускоряет работу — логику и экраны не нужно дублировать. Проблема проявляется на втором релизе, когда модулей становится больше и каждый живёт по своему графику.
К этому моменту общий код и данные разрослись, и любая правка в базовом модуле задевает соседние. Связанность модулей приложения растёт неявно — через общие модели, кэш, навигацию, настройки окружения. Сборка перестаёт быть предсказуемой: изменение в одном разделе ломает другой, а проверка требует прогонять сценарии всего продукта.
Появляется единая точка отказа. Общий слой — состояние сессии, конфигурация, разделяемый экран — роняет не отдельный сценарий, а приложение целиком, включая разделы, которых правка не касалась. Ошибка в общем модуле проявляется у всех пользователей сразу, и локализовать её по логам становится сложно.
Время выпуска релиза растёт: вместо изолированной доставки одного модуля команда согласует даты со всеми, кто затрагивает общий код. Релиз превращается в переговоры и синхронную проверку, а срочное исправление требует полного пересбора и повторного прохождения всех проверок — включая те, что к изменению не относятся.
Это не следствие слабой команды, а результат того, как проведены границы между разделами продукта. Дальше разбираем, как это закрывается: контракты между модулями, независимая сборка, изоляция сбоев и свои данные у каждого раздела.
Что даёт модульное ядро: релизы, отказоустойчивость, нагрузка
Модульное ядро разносит экран, доменную логику и интеграции по независимым модулям с явным контрактом. Контракт описывает, что модуль отдаёт наружу, и запрещает обращаться к внутренностям соседа напрямую. Ядро остаётся тонким: навигация, граф зависимостей, общий дизайн-слой — всё остальное подключается отдельной сборкой.
Независимые выпуски модулей меняют сам цикл релиза. Команда собирает и выкатывает свою часть, не дожидаясь остальных: полный прогон тестов сокращается до проверок изменённого модуля и его контрактов, а общая сборка перестаёт быть точкой блокировки. Модули на разных стеках живут рядом — часть кросс-платформенных блоков удобно собирать на Flutter, тяжёлые участки остаются нативными.
Отказоустойчивость приложения держится на изоляции сбоев. Падение модуля оплаты не уносит каталог и ленту: ядро перехватывает ошибку, помечает модуль недоступным и показывает деградированный сценарий вместо закрытия приложения. Крашлитика ведётся по модулям, поэтому видно, какая доля падений локализована внутри одного блока, и правка не требует пересборки всего продукта.
Масштабирование под нагрузкой — следствие той же границы. Тяжёлые сценарии (лента, поиск, рекомендации) уходят в отдельные сервисы и растут по своей метрике, независимо от остальных. Приложение подгружает модули по требованию, поэтому время холодного старта не увеличивается вместе с числом функций, а в пике отказывает конкретный сервис: остальные разделы продолжают работать на кэше и локальных данных.
Способы сборки приложения: монолит, модульный монолит, сервисы
Выбор компоновки зависит не от модности, а от того, сколько команд работает над продуктом и насколько независимо им нужно выпускать изменения. Пока модулей пять и команда одна, разделение по сервисам приносит больше накладных расходов на взаимодействие, чем пользы. Когда направлений три-четыре и у каждого свой ритм релизов, скорость выпуска начинают определять именно границы модулей.
На практике платформы проходят путь от единого приложения к модульному монолиту, а в выделенные сервисы выносят отдельные узлы — платежи, уведомления, поиск. Ниже — применимость и ограничения каждого варианта.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Единое приложение | Один продукт, одна команда, короткий список сценариев, этап проверки спроса | Общая сборка: правка в одном экране тянет релиз целиком, время сборки растёт, растут пересечения между областями |
| Модульный монолит | Несколько команд и направлений в одном продукте, нужны независимые релизы без эксплуатации распределённой системы | Нужна дисциплина: границы модулей задаются правилами сборки, иначе связи прорастают и модуль теряет самостоятельность |
| Выделенные сервисы | Узлы с отдельной нагрузкой, своим ритмом изменений и требованиями к отказоустойчивости: платежи, уведомления, каталог | Задержки на обмене, распределённые транзакции, отдельный мониторинг и версионирование контрактов между узлами |
| Гибрид | Часть узлов созрела до самостоятельности, а ядро ещё меняется сообща | Нужны чёткие контракты и регламент, иначе состояние расходится между ядром и сервисами |
Набор модулей и места, где проходят их границы, фиксируем до старта разработки: от этого зависят структура репозиториев, схема сборки и порядок выпуска релизов.
Этапы проектирования платформы: от схемы до передачи
Проектирование платформы начинаем с инвентаризации: какие сервисы уже работают, что переиспользуем, где дублируются авторизация, платежи и уведомления. На выходе этапа — согласованная схема модулей и контракты между модулями; без них супер-приложение превращается в набор приложений под одной иконкой.
- Разбор текущего состояния. Карта экранов, сервисов и точек интеграции, узкие места и зависимости, которые блокируют независимые релизы.
- Схема модулей. Границы: ядро оболочки, общие сервисы, доменные модули. Критерий — модуль собирается, проверяется и выпускается, не трогая остальные.
- Контракты между модулями. Форматы обмена, версионирование, поведение при недоступном соседе. Обновлённый модуль не должен ломать уже выпущенную версию приложения.
- Окружения и сборка. Разводим среды разработки, предрелизной проверки и выпуска, выносим настройки из кода, настраиваем автоматическую сборку с общим порядком выпуска.
- Проверка архитектуры. Сценарии отказа модуля, обновление без остановки приложения, рост нагрузки; проверяем на реальных устройствах и слабых сетях.
- Передача команде. Отдаём схемы, документацию, регламент добавления нового модуля и проводим обучение — чтобы платформу развивала команда заказчика.
Схемы модулей, контракты сервисов и регламенты релизов
Архитектура Super App живёт дольше команды, которая её собрала, — но только если решения зафиксированы в артефактах, а не в переписке. Сдача платформы идёт по перечню приёмки: заказчик получает комплект, по которому продукт развивают своими силами или передают другой команде без обратного проектирования. Что в него входит — ниже.
- Карта модулей — зона ответственности каждого модуля, его зависимости и точки расширения. По ней видно, что меняется изолированно, а что потянет за собой соседей.
- Описание обмена данными — контракты между сервисами, форматы сообщений, правила версионирования и поведение при недоступности соседа: повторные попытки, очередь, режим деградации.
- Правила доступа — роли и области видимости, точки проверки прав, порядок выдачи, продления и отзыва ключей между модулями и внешними системами.
- Регламент выпуска релиза — ветвление, обязательные автоматические проверки, этапы выката, критерии отката и порядок действий при сбое.
- Документация платформы — схема окружений, сборка и подпись приложения, перечень внешних интеграций и границы ответственности сторон.
- Журнал архитектурных решений — какие варианты рассматривали, что выбрали и почему, с причинами отказа от альтернатив. Восстанавливать это по памяти дороже всего.
- Сценарий подключения нового модуля — пошагово: какие контракты описать, где зарегистрироваться, какие проверки пройти до выката.
Комплект живёт вместе с продуктом: правка контракта или регламента выпуска идёт одним изменением с документом. На приёмке проверяем это практикой — открываем карту по любому модулю и сверяем с тем, как он собран.
Кейс: как приложение выдержало рост и ускорило выпуск релизов
На входе был монолит: одна сборка, общий релизный конвейер на все команды и единая кнопка «выпустить». При росте пользовательской базы в разы это стало узким местом — правка одного экрана ждала общего релиза, а сбой в отдельном домене (платежи, доставка, поддержка) приводил к откату всего клиента. Время восстановления доходило до шести часов, потому что пересобирать и проверять приходилось всю сборку целиком.
Что изменили
Домены вынесли в независимые модули с версионированными контрактами, а навигацию, авторизацию и аналитику оставили в общем слое. Каждая команда получила свой конвейер: сборка модуля, проверки по контракту, поэтапная раскатка на долю аудитории и быстрый откат. Серверную часть развели по сервисам и запустили в Kubernetes — откат затрагивает один сервис и его контракт, а не всю платформу.
Что стало
Выпуск релизов по командам ускорился: вместо ожидания общей даты — несколько дней от готовности кода до аудитории, часть изменений приезжает удалённой конфигурацией вообще без обновления приложения. Время восстановления после сбоя сократилось с часов до минут. Плата за независимость — общий слой: правки в навигации и авторизации проходят отдельное ревью, иначе модули снова начинают тянуть друг друга.
Чем модульный super app отличается от набора отдельных приложений
Модульный super app — это одно приложение-контейнер, внутри которого живут независимые модули: витрина, заказы, платежи, доставка, личный кабинет. Контейнер держит навигацию, единый вход, общий дизайн-слой и механику обновлений, а каждый модуль собирается, тестируется и версионируется отдельно. Пользователь ставит одно приложение и получает все сервисы с одним профилем, одной корзиной и одной историей операций.
Набор отдельных приложений устроен иначе: каждый продукт тянет свою авторизацию, свой платёжный контур, свои уведомления, аналитику и экран поддержки. В типовом ландшафте 60-70% кода дублируется между кодовыми базами, а правка в правилах безопасности или в схеме оплаты повторяется столько раз, сколько приложений в портфеле. Дальше расходятся версии общей библиотеки — и команды начинают ломать совместимость друг другу.
Цена проявляется на релизах. Контейнер позволяет выпускать сервисные изменения внутри себя, не запуская заново полный цикл проверки в App Store, тогда как каждая сборка из набора идёт своим согласованием. Общая платформа даёт то, что не собрать по частям: сквозную аналитику по всем сервисам, единую сессию, общий поиск и рекомендации. Новый раздел выводится как модуль за один релизный цикл, а не как отдельный продукт со своим описанием в магазине и своей поддержкой.
Обратная сторона модульности — требования к дисциплине. Нужны жёсткие контракты между модулями, версионирование интерфейсов и изоляция сбоев: без этого падение одного раздела уносит весь контейнер. Ещё на старте фиксируем, какие части живут в общей платформе, а какие остаются автономными, — иначе модульный super app вырождается в те же разрозненные приложения, только внутри одного окна.
Технические сомнения перед стартом: интеграции, данные, поддержка
Сомнения перед стартом обычно касаются не самого супераппа, а швов вокруг него: как он стыкуется с системами, которые уже работают, что происходит с накопленными данными и кто отвечает за платформу после запуска. Ниже — четыре вопроса, которые задают чаще всего, и то, как мы отвечаем на них на уровне архитектуры.
Как суперапп срастётся с текущими системами?
Мы не переписываем работающие системы, а ставим между ними и платформой слой адаптеров: каждая интеграция получает идемпотентные вызовы, повторы с нарастающей паузой и явную деградацию. Если внешний сервис недоступен, модуль отдаёт последние корректные данные вместо ошибки на экране.
Как переносятся данные без простоя?
Схема — снимок плюс догон изменений по журналу, затем сверка по каждой сущности: число записей, контрольные суммы, ссылочная целостность. Переключение делаем после теневого прогона на реальном трафике, с точкой возврата на исходную систему.
Что с правами доступа и учётными записями?
Единая модель ролей и атрибутов, единый вход с существующим каталогом пользователей и проверка прав на уровне сервиса, а не интерфейса. Действия с чувствительными данными попадают в журнал аудита, а модули получают минимально необходимый объём доступа.
Что входит в сопровождение платформы после запуска?
Модули обновляются независимо, поэтому релиз одного раздела не тянет за собой остальные. Настраиваем метрики и оповещения по ключевым путям, регламент выпуска версий и обновление под требования магазинов приложений и актуальных версий операционных систем.
Обсудим задачу и вернёмся с оценкой и планом работ
Чем конкретнее исходные данные на входе, тем меньше допущений в оценке. Поэтому к разговору полезно собрать не пожелания к дизайну, а фактическое состояние продукта: какие сервисы уже существуют внутри, как они авторизуют пользователя и где хранят его данные. Дальше мы превращаем это в карту модулей и границы ядра.
- Перечень сервисов-модулей, которые должны жить в одном приложении, и того, что остаётся отдельными продуктами.
- Схема текущей авторизации и единого профиля: где выдаются токены, как организован выход из аккаунта, есть ли уже сквозная сессия между сервисами.
- Платежный контур и работа с внешними поставщиками: кто инициирует платёж, где хранится история операций, какие проверки обязательны.
- Требования к нагрузке и режимам без сети: какие экраны обязаны открываться из локального кэша, а какие допустимо подгружать по запросу.
- Доступы к учётным записям магазинов приложений, к серверам сборки и к системам аналитики — их оформление часто занимает больше времени, чем первый этап разработки.
- Ограничения: платформенные правила, внешние требования к хранению персональных данных, версии операционных систем, которые нужно поддержать на старте.
После обсуждения задачи мы возвращаемся с оценкой и планом работ: состав команды под конкретный объём — архитектор, инженеры платформенных модулей, мобильные разработчики, специалист по сборке и выпуску, — разбивка по этапам, точки интеграции и порядок подготовки к старту. Опишите задачу в свободной форме, приложите то, что уже есть по списку выше, — этого достаточно, чтобы начать предметный разговор.







