Справочная архитектура. Это иллюстративная архитектура и контрольный список объёма работ, а не подтверждённый клиентский проект и не результат измеренного внедрения. Технологии, объём интеграции и результаты поставки согласовываются для конкретного технического задания.
Сценарий и ограничения
Продукт обслуживает множество клиентских организаций в рамках одного развёртывания. Решение, которое определяет всю архитектуру, — модель изоляции: общие таблицы с колонкой tenant, отдельная схема для каждого арендатора или отдельная база данных для каждого арендатора. Выбор варианта по умолчанию вместо осознанного проектирования — самая дорогостоящая ошибка в этой категории, поскольку последующее изменение требует миграции актуальных данных клиентов.
Архитектура
Слои и зоны ответственности
| Слой | Технология | Зона ответственности |
|---|---|---|
| Web | Next.js (SSR для маркетинговых страниц и SEO, SPA после входа) | Публичные страницы используют серверный рендеринг для видимости в поиске; авторизованному продукту он не требуется, поэтому он остаётся клиентским приложением. |
| API | Go + Gin, арендатор определяется для каждого запроса | Контекст арендатора определяется по субдомену или токену до запуска любого обработчика, а затем передаётся через каждый запрос к данным. |
| Хранилище | PostgreSQL, общая схема с ограничением строк по арендатору | Одна база данных с tenant_id в каждой таблице, принадлежащей арендатору, с обеспечением на уровне репозитория и, где поддерживается, с помощью row-level security как дополнительного уровня защиты. |
| Кэш | Redis, ключи с префиксом арендатора | Сессии, ограничения частоты запросов и часто используемая конфигурация. Префиксы ключей предотвращают классическое столкновение ключей кэша, при котором данные одной клиентской организации могут попасть к другой. |
| Биллинг | Stripe или региональный платёжный шлюз | Состояние подписки дублируется локально, поэтому проверки доступных возможностей никогда не зависят от активного обращения к платёжному провайдеру. |
| Задания | Воркеры очереди с контекстом арендатора | Плановые и асинхронные задачи; контекст арендатора передаётся вместе с данными задания, а не определяется во время выполнения. |
Модель данных
В приведённых ниже таблицах зафиксированы правила, от которых зависит всё остальное. Именно ошибки на этом уровне превращают работающий демонстрационный прототип в систему, которую невозможно расширять.
Основные сущности
| Сущность | Ключевые поля, связи и правила |
|---|---|
| tenant | Запись об организации с тарифом, статусом, регионом и флагами функций. Каждая таблица, принадлежащая арендатору, содержит tenant_id, и ни один запрос не может обходиться без него. |
| user / membership | Пользователь может состоять в нескольких организациях с разными ролями в каждой из них, поэтому идентичность является глобальной, а права доступа определяются для каждого членства. Моделирование user и membership в одной таблице делает поддержку нескольких организаций невозможной в будущем. |
| role / permission | Права назначаются ролям, роли назначаются для каждого членства, а каждая проверка выполняется на backend. Скрытие элементов во frontend является только представлением и никогда не заменяет контроль доступа. |
| subscription / entitlement | Тариф, количество пользовательских мест или лицензий, период и производные доступные возможности. Доступ к функциям определяется на основе локально сохранённых доступных возможностей по подписке, поэтому сбой платёжного провайдера не блокирует клиентов в продукте. |
| audit_log | Инициатор, арендатор, действие, цель или объект аудита и данные до/после. Поддерживает проверку безопасности и анализ инцидентов; требования к сроку хранения, доступу и аудиту необходимо согласовать до начала реализации. |
| tenant_config | Настройки, брендинг и переопределения функций для каждого арендатора, разрешаемые с документированным приоритетом относительно настроек тарифа по умолчанию. |
Ключевые интерфейсы
Конечные точки, содержащие бизнес-правила
| Конечная точка | Назначение и особенности конкурентного доступа |
|---|---|
| POST /api/v1/auth/login | Аутентифицирует пользователя, а затем возвращает доступные ему членства в организациях; арендатор выбирается явно, а не определяется по последней сессии. |
| GET /api/v1/{resource} | Каждое чтение в рамках арендатора проходит через репозиторий, который добавляет tenant_id. Ограничение области действия находится в одном месте, поэтому обработчик не может забыть о нём — это самый распространённый источник утечек между клиентскими организациями. |
| POST /api/v1/webhooks/billing | Webhook платёжного провайдера, идемпотентный по идентификатору события и обновляющий локальное состояние подписки и доступных возможностей по подписке. |
| POST /api/v1/tenants/{id}/invite | Процесс приглашения, создающий членство с ролью; частота запросов ограничивается для каждого арендатора, чтобы предотвратить злоупотребления приглашениями. |
| GET /api/v1/audit | Запрос журнала аудита с ограничением по арендатору и постраничной выдачей, доступный администраторам арендатора как самостоятельный способ подтвердить соответствие требованиям. |
Технические решения
- Общая схема с tenant_id, выбранная осознанно. Это наиболее экономичный вариант с точки зрения эксплуатации и миграции, подходящий для большинства продуктов. Если договор с клиентом требует физического разделения, та же кодовая база может работать в выделенном развёртывании — этот путь проектируется с самого начала, а не обнаруживается во время переговоров о продаже.
- Ограничение области арендатора реализовано на одном уровне репозитория. Расчёт на то, что каждый разработчик будет помнить о добавлении условия WHERE, приводит к утечкам между клиентскими организациями. Централизация делает случайное написание небезопасного запроса затруднительным.
- Доступные возможности по подписке дублируются локально. Проверка платёжного провайдера при каждом запросе добавляет задержку и создаёт жёсткую зависимость. Локальное дублирование означает, что сбой провайдера ухудшает операции биллинга, но не работу самого продукта.
- Журнал аудита с первого релиза. Восстановить историю аудита задним числом невозможно. Подтвердите требования покупателя к аудиту и сохраняйте согласованную историю начиная с первого релиза.
- SSR только для публичных страниц. Маркетинговым страницам и документации нужна видимость в поиске; авторизованному продукту она не требуется, а принудительное использование SSR добавляет затраты без отдачи.
Гипотетические целевые показатели проектирования
Приведённые ниже значения являются гипотетическими примерами для планирования ёмкости, а не измеренными результатами для клиента, подтверждённой рекомендацией по конфигурации или SLA. Устанавливайте проектные критерии приёмки после определения нагрузки, устройств, данных, оборудования и зависимостей от сторонних систем; проверяйте их с помощью пилотного запуска и нагрузочных тестов до принятия целевого показателя для промышленной эксплуатации.
Целевые показатели ёмкости и производительности
| Цель | Значение и допущение |
|---|---|
| Задержка API | p95 менее 250 мс для чтения в рамках арендатора при наличии корректных составных индексов, начинающихся с tenant_id. |
| Изоляция арендаторов | Требуется автоматизированный набор тестов, который пытается получить доступ между арендаторами для каждой конечной точки и прерывает сборку при несанкционированном доступе. Реализация должна проходить эти проверки; данный справочный материал не является доказательством завершённого тестирования безопасности. |
| Подключение | Создание и подготовка нового арендатора выполняются за секунды, поскольку это добавление строки и записи конфигурации, а не инфраструктурная работа. |
| Масштабирование | Рассчитано на несколько тысяч арендаторов на одном экземпляре PostgreSQL; после этого предусматривается переход к репликам для чтения, а затем к шардированию по арендаторам, но эти этапы планируются без преждевременной реализации. |
Что входит в поставку
- Исходный код frontend на Next.js, backend на Go и панели администратора в вашем репозитории
- Документированная схема базы данных с ограничением области по арендатору, индексами и таблицами аудита, а также история миграций
- Набор тестов изоляции между арендаторами, который можно запускать в вашей системе непрерывной интеграции
- Интеграция биллинга, обработка webhook и документация по доступным возможностям подписки
- Инструкции по развёртыванию Docker и Nginx, конфигурация окружения, процедура резервного копирования и восстановления
Планирование под ваш бизнес
Описанные выше модули являются отправной точкой, а не фиксированным пакетом. Обычно мы ограничиваем первый релиз одним основным рабочим процессом и одним административным процессом, а затем расширяем продукт, когда реальное использование показывает, где находятся фактическая нагрузка и нестандартные случаи. Отправьте описание объёма работ, и мы сопоставим его с этой архитектурой и сообщим, какие части пока не понадобятся.
