Движок без движка: архитектура, которая растёт вместе с требованиями
Современные фреймворки обычно начинают с предположения, что приложению заранее понадобится довольно много инфраструктуры. Мы выбираем стек, создаём приложение, получаем runtime, роутинг, сборщик, серверную часть, клиентскую часть и десятки зависимостей — ещё до того, как стало понятно, нужны ли они конкретной задаче.
С AI-разработкой у этой модели появляется дополнительная цена. Чем больше исходная система, тем больше контекста должен изучить агент, тем больше неявных связей ему приходится учитывать и тем сложнее проверить локальное изменение.
Поэтому для новой версии нашего движка мы рассматриваем противоположный принцип: архитектура должна появляться только тогда, когда её требует задача.
Если достаточно статики — движок не нужен
Представим обычный корпоративный сайт. Несколько страниц, контакты, описание услуг, изображения.
Для него может быть достаточно:
static files
+ Docker Compose
+ Traefik
Ни база данных, ни GraphQL, ни авторизация, ни React, ни полноценный application server здесь не дают обязательной ценности.
Изменение статического файла почти бесплатно. AI-агенту не нужно изучать большой framework, чтобы поменять телефон, добавить страницу или переделать блок на главной.
Поэтому важный принцип звучит так:
Нулевая функциональность должна иметь почти нулевую архитектурную стоимость.
Это отличается от привычного подхода «сначала установим движок, потом отключим всё ненужное». Если задаче не нужен движок — его действительно не должно быть.
Архитектура растёт вслед за требованиями
Допустим, через некоторое время сайту понадобилось хранить данные.
Тогда появляется причина добавить PostgreSQL и Prisma.
static
↓
PostgreSQL + Prisma
Теперь у проекта есть типизированная работа с базой, но это ещё не означает, что ему нужен публичный API или сложный frontend.
Появилась необходимость предоставить данные другим клиентам — добавляем API. Например, Pothos и GraphQL.
Prisma
↓
Pothos
↓
GraphQL API
Появился web-интерфейс, которому нужен этот API, — добавляем GraphQL Code Generator и подходящий клиент, например Apollo.
Prisma
↓
Pothos
↓
GraphQL
↓
Codegen
↓
Typed frontend client
В результате типы проходят от базы до клиента без необходимости вручную описывать одну сущность в нескольких местах.
Но принципиально важно другое: ни один из этих уровней не является обязательным заранее.
Где-то нужен API без frontend. Где-то нужен frontend, работающий с внешним API, и собственная база вообще не нужна. Где-то Prisma используется из CLI или worker-процесса. Где-то небольшой HTTP endpoint решает задачу лучше полноценного GraphQL-слоя.
Это не лестница технологий, которую обязан пройти каждый проект. Это граф возможных путей развития.
Минимально достаточная архитектура
Отсюда появляется основной инженерный принцип:
Используй самую дешёвую архитектуру, которая полностью решает текущую задачу.
Это особенно важно при работе с coding agents. AI легко переусложняет решение: простой сайт может неожиданно получить React, Next.js, API routes, ORM и набор инфраструктурных зависимостей просто потому, что такие решения часто встречаются в обучающих примерах.
Мы хотим заложить противоположную культуру.
Новая зависимость должна появляться не потому, что «так принято в нашем framework», а потому, что возникло требование, которое оправдывает эту зависимость.
Нужна реляционная persistence — появляется Prisma и база.
Нужен типизированный программный API — появляется соответствующий API-слой.
Нужен клиент к нему — появляется codegen.
Нужна авторизация — добавляется подходящий механизм авторизации.
Нужна очередь — появляется очередь.
Пока потребности нет, нет и архитектурного налога.
Почему готовые модули — не главное
Первая очевидная идея для расширяемого движка — сделать каталог модулей: auth, billing, knowledge base, tasks, files и так далее.
Такие модули могут быть полезны, но они быстро создают новую жёсткость.
Готовый auth фактически говорит разработчику: «Вот наша реализация авторизации. Встрой свой проект в неё».
Для AI-assisted development может быть полезнее другое:
Вот несколько проверенных способов добавить авторизацию. Вот условия, при которых каждый из них разумен. Вот законченный пример изменения проекта. Выбери подходящий вариант и адаптируй его к текущим требованиям.
То есть основной актив — не обязательно готовый package. Это база архитектурных кейсов и best practices.
Кейс — это законченное вертикальное изменение
Хороший кейс начинается не с технологии, а с изменения требований.
Например:
Исходное состояние:
статический корпоративный сайт
Новое требование:
сохранять обращения из формы
Решение:
добавить минимальный backend и persistence
Изменения:
- база
- модель данных
- endpoint
- форма
- конфигурация запуска
Проверка:
отправить форму и убедиться, что запись сохранена
Другой кейс может начинаться с того же сайта, но иметь другое требование:
Новое требование:
отправлять сообщения с формы на внешний сервис
Тогда база вообще может не понадобиться.
Это важнее документации вида:
How to add Prisma
How to add Pothos
How to add Apollo
Такая документация объясняет технологии. Нас интересует база инженерных решений:
Было состояние X. Возникло требование Y. Минимальное разумное изменение — Z. Вот почему. Вот альтернативы. Вот как проверить результат.
Кейсы как процедурная память для AI
Coding agent способен не только копировать готовый код. Он может изучить законченное изменение, понять его структуру и перенести принцип на похожую задачу.
Поэтому кейс должен содержать как минимум:
- исходное состояние проекта;
- новое требование;
- выбранное архитектурное решение;
- конкретные изменения;
- причины выбора;
- существенные альтернативы;
- способ проверки результата.
В таком виде коллекция кейсов становится своего рода процедурной памятью проекта.
Агент получает не гигантскую документацию всего framework, а несколько релевантных примеров того, как система эволюционирует.
Сквозная типизация как обратная связь для AI
Когда архитектура всё-таки становится сложнее, особенно важна проверяемость изменений.
Например, для приложения с базой, GraphQL API и frontend можно построить цепочку:
Prisma schema
↓
generated Prisma types
↓
Pothos
↓
GraphQL schema
↓
GraphQL Codegen
↓
frontend types
↓
tsc
Здесь типизация — не только удобство разработчика.
Компилятор становится частью feedback loop coding agent. Если агент изменил модель данных, но неправильно протянул изменение до API или клиента, система должна дать ему конкретную машинно читаемую ошибку.
Чем меньше ручного дублирования контрактов, тем меньше возможностей получить незаметное расхождение между слоями.
Поэтому мы хотим выводить и генерировать типы там, где это возможно, но избегать скрытой магии, которую агенту трудно понять и диагностировать.
Движок как архитектурный протокол
Из этого возникает немного необычный вывод: возможно, будущий «движок» вообще не должен быть единым runtime или npm-пакетом.
Не обязательно должен существовать момент:
npm install our-engine
после которого проект становится «проектом на нашем движке».
Вместо этого может существовать минимальный набор совместимых conventions:
- как проект запускается;
- как сервисы подключаются к инфраструктуре;
- как добавляются данные;
- как строятся типизированные API;
- как клиент получает контракты;
- как проверяются изменения;
- как оформляются новые архитектурные кейсы.
Тогда два проекта могут использовать совершенно разный набор технологий, но оставаться понятными одному и тому же AI-агенту, потому что следуют общим принципам эволюции.
В этом смысле движок становится скорее архитектурным протоколом, чем библиотекой.
Showcase должен показывать пути развития
Поэтому демонстрационные проекты тоже стоит строить не как огромные приложения «со всем из коробки».
Гораздо показательнее история последовательных изменений:
00-static-site
01-add-persistence
02-add-api
03-add-typed-client
04-add-admin-ui
05-add-auth
И рядом альтернативная ветка:
00-static-site
01-add-contact-endpoint
На втором шаге задача решена — дальнейшее усложнение не требуется.
Ещё один путь может выглядеть так:
00-api-service
01-add-database
02-add-agent-actions
и вообще не иметь frontend.
Такие showcase одновременно выполняют несколько функций: демонстрируют архитектурные принципы, служат рабочими примерами для AI, проверяют совместимость решений и дают людям основу для собственных экспериментов.
Что тогда является настоящим продуктом
Главной ценностью становится не количество функций, поставляемых из коробки.
Ценность — стоимость добавления следующей необходимой функции.
Можно измерять, сколько контекста понадобилось агенту, сколько частей проекта пришлось изменить, сколько контрактов пришлось продублировать вручную, смог ли агент самостоятельно проверить результат и насколько легко существующий кейс переносится на новую задачу.
Это можно рассматривать как Agent Experience — AX, аналог developer experience, но для coding agents.
Хорошая система должна позволять стороннему AI получить задачу, найти несколько релевантных кейсов, понять текущее состояние проекта, выбрать минимально достаточное решение, реализовать его и самостоятельно проверить результат без постоянных подсказок автора архитектуры.
От готовой функциональности к способности создавать функциональность
У большого готового движка есть очевидная ценность: пользователь сразу получает много возможностей.
Но вместе с ними он получает и всю архитектурную стоимость этих возможностей.
Мы хотим проверить другую модель.
Не давать каждому проекту базу, API, frontend framework, авторизацию, knowledge base, billing, workers и десятки интеграций заранее.
Начать почти с ничего.
А затем иметь достаточно хорошие принципы, совместимые строительные блоки и базу проверенных кейсов, чтобы человек вместе с AI мог быстро прийти именно к той системе, которая нужна ему.
Если этот подход сработает, открытые кейсы могут стать ещё и механизмом развития сообщества. Один человек решает новую задачу, оформляет её как воспроизводимый кейс, следующий использует этот опыт как образец, адаптирует его и добавляет следующий путь развития.
Получается цикл:
требование
↓
минимальное решение
↓
проверенный кейс
↓
повторное использование AI
↓
новые проекты и новые кейсы
Именно поэтому сейчас нам интереснее не каталог готовых модулей, а база принципиальных showcase, best practices и законченных вертикальных изменений.
Не максимальное количество возможностей в исходной системе, а возможность максимально дёшево добавить ровно одну следующую возможность, которая действительно понадобилась.