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







