Почему первый MVP GenAI-платформы я не стал превращать в микросервисы
После проектирования архитектуры возникает следующая проблема: как начать писать реальный код и не разрушить собственные архитектурные решения первой же реализацией.
Для Enterprise GenAI Platform решил проверить Architecture Baseline на одной небольшой Full Stack вертикали:
React + TypeScript -> ASP.NET Core -> EF Core -> PostgreSQL
В качестве первого сценария взял Chats.
Не потому что чат это самая важная функция будущей платформы, наоборот: сценарий достаточно простой, чтобы на нём проверить саму архитектуру.
Главный вопрос был не в том получится ли сделать POST /chats.
Нужно было проверить несколько вещей.
Core API пока остаётся Modular Monolith.
Можно было сразу вынести Chats в отдельный сервис. Но у него пока нет независимого жизненного цикла, отдельных требований к масштабированию или собственного технологического стека.
Отдельный сервис сейчас означал бы только дополнительную сетевую границу, deployment и новые точки отказа.
Модуль ещё не микросервис.
PostgreSQL используется сразу, без временного in-memory хранилища.
Иначе вертикаль проверяла бы только UI и HTTP API, но не реальный persistence.
С появлением PostgreSQL сразу становятся видны настоящие инфраструктурные вопросы: migrations, lifecycle DbContext, конфигурация подключения, ошибки базы и health checks.
EF Core остаётся основным способом доступа к данным.
Dapper не запрещён, но пока нет задачи где он решает реальную проблему.
Принцип простой:
- EF Core по умолчанию
- Dapper точечно когда появляется измеримая причина
Frontend не знает внутреннее устройство backend.
React работает только через HTTP контракт. Ему не важно какая ORM используется, как называется таблица или как организованы модули внутри Core API.
Это позволяет менять реализацию backend не протаскивая внутренние изменения во frontend.
Server state сразу отдан TanStack Query.
После создания Chat frontend не пытается вручную поддерживать копию серверных данных.
Mutation инвалидирует chats после чего актуальное состояние снова приходит с сервера.
Источник истины остаётся на backend.
Получилась первая настоящая вертикаль:
UI -> HTTP -> Core API -> PostgreSQL -> refetch -> UI
Рабочая вертикаль это не только happy path.
Поэтому уже здесь появились Correlation ID, structured logging, PostgreSQL aware health check, backend и frontend tests.
И отдельно End-to-End проверка:
Chat создаётся через React -> сохраняется в PostgreSQL -> появляется после повторного запроса -> остаётся после перезагрузки страницы.
Именно reload здесь особенно важен: он доказывает что UI показывает не локальную иллюзию сохранения, а состояние из реальной базы.
При этом пока что не добавляется Kubernetes, Kafka, service mesh, отдельные микросервисы и полноценный distributed tracing.
Не потому что они не понадобятся, а потому что текущая задача пока не дала причины платить за эту сложность.
Полную техническую версию с кодом, структурой solution, EF Core, TanStack Query, тестами и End-to-End acceptance опубликовал на Хабре.
Полная статья на Хабре
Исходный код проекта на GitHub.