Перейти к контенту
B2B-платформы

Multi-tenant в SaaS: закладывать сразу или переделывать потом

Три модели изоляции данных в multi-tenant SaaS — отдельная база, общая база с tenant_id, отдельная схема. Что стоит переделка задним числом и когда multi-tenant не нужен.

Автор: Николай Мазур · · 9 мин чтения

Короткий ответ: закладывать multi-tenant стоит тогда, когда второй клиент появится в обозримом горизонте — примерно в течение года. Переделка работающей однопользовательской системы обходится не в «добавить колонку tenant_id», а в ревизию каждого запроса к базе, каждой фоновой задачи и каждой выгрузки. Но если второго клиента не предвидится, это преждевременная сложность, за которую платят скоростью.

Разберём, из чего складывается решение.

Что такое tenant на практике

Tenant — это изолированный контур данных одного клиента внутри общей системы. Пользователи разных тенантов работают в одном приложении, но не видят данных друг друга и, в идеале, даже не знают о существовании соседей.

Звучит просто, пока не доходит до деталей. Настройки, брендирование, тарифы, справочники, права ролей, интеграции с внешними системами, фоновые задачи, отчёты, экспорт — всё это должно понимать, к какому тенанту относится. Пропущенное место — это утечка данных между клиентами, худший тип бага в SaaS.

Три модели изоляции

Сравнение трёх моделей изоляции данных в multi-tenant SaaS: отдельная база данных на каждого клиента даёт максимальную изоляцию но дорогая в эксплуатации, отдельная схема в общей базе — компромисс, общая таблица с колонкой tenant_id — дешевле всего но требует дисциплины на уровне каждого запроса

Изоляция и стоимость эксплуатации меняются в противоположные стороны. Выбор — это компромисс, а не поиск лучшего варианта.

Отдельная база на клиента. Максимальная изоляция: физически разные базы, утечка между тенантами практически исключена. Легко вывезти данные одного клиента, легко восстановить из бэкапа только его. Расплата — эксплуатация: миграции надо прогонять на каждой базе, мониторинг умножается, а подключения к сотне баз упираются в лимиты. Разумно при десятках клиентов с высокими требованиями к изоляции, не при тысячах.

Отдельная схема в общей базе. Компромисс: одна база, у каждого клиента своя схема с одинаковым набором таблиц. Изоляция слабее физической, но заметно лучше общей таблицы. Миграции идут по всем схемам, что дольше, чем по одной, но проще, чем по сотне баз. Хорошо работает на десятках и сотнях клиентов.

Общая таблица с колонкой tenant_id. Все данные в одних таблицах, разделение — по значению колонки. Дешевле всего в эксплуатации и лучше всего масштабируется. Но безопасность держится на дисциплине: любой запрос без фильтра по тенанту становится утечкой. Здесь обязательна защита на уровне базы — в PostgreSQL это row-level security, а не только фильтры в коде приложения.

Что реально ломается при переделке

Опыт показывает, что «добавить tenant_id» — самая маленькая часть работы. Ломается остальное.

Фоновые задачи. Обработчики очередей, крон-задачи, рассылки писались в предположении «обрабатываем всё». После введения тенантов каждая задача должна знать, в чьём контексте выполняется. Пропущенная задача либо падает, либо, что хуже, обрабатывает чужие данные.

Кеш. Ключи кеша без тенанта — прямой путь к тому, что клиент A увидит данные клиента B. Такой баг воспроизводится не всегда и обнаруживается в самый неудачный момент.

Файлы. Загруженные документы, экспорты, отчёты лежат в хранилище по путям, которые тоже надо разделять. И проверять права при выдаче, а не полагаться на неугадываемость ссылки.

Уникальные ограничения. Email пользователя был уникален глобально — теперь он уникален в пределах тенанта. Артикул номенклатуры, номер договора, код — то же самое. Каждое такое ограничение в базе надо пересобрать, и это миграция с риском.

Интеграции и вебхуки. Внешняя система шлёт событие — надо понять, чьё оно. Если раньше было очевидно, теперь нужен маршрутизирующий слой.

По совокупности переделка работающей системы обычно стоит дороже, чем закладывание с самого начала. Но не в разы — и это важно, потому что превращает вопрос в экономический, а не в догматический.

Когда multi-tenant не нужен

Честный список причин отказаться:

  • клиент один и второго не планируется — например, внутренняя система компании;
  • каждый клиент требует существенно разной логики, а не разных настроек: тогда это не один продукт, а несколько похожих;
  • требования к данным таковы, что клиент вообще не согласится на общую инфраструктуру — например, развёртывание в собственном контуре;
  • проект в стадии проверки гипотезы, и вероятность, что продукт останется в текущем виде, невысока.

В последнем случае разумный компромисс — не строить полноценный multi-tenant, но и не мешать себе: с самого начала не завязываться на глобальную уникальность, не хардкодить настройки и держать данные клиента отделимыми. Это почти ничего не стоит на старте и заметно удешевляет переделку, если она понадобится.

Что закладывать, если решили делать сразу

Минимальный набор, который окупается:

Идентификатор тенанта в контексте запроса, проставляемый один раз на входе, а не передаваемый вручную в каждую функцию. Защита на уровне базы, а не только в коде. Тесты, которые специально проверяют, что данные одного тенанта не видны из-под другого — их пишут редко, а именно они ловят самые опасные ошибки. И механизм миграций, который умеет прогоняться по всем контурам предсказуемо.

Отдельно — возможность выгрузить и удалить данные конкретного клиента. Это понадобится и при расставании с клиентом, и по требованиям законодательства о персональных данных.

Сроки и стоимость

Ориентиры: закладывание multi-tenant с нуля добавляет к MVP примерно 15–25% времени — это архитектурные решения, изоляция и тесты на неё. Переделка работающей системы среднего размера занимает от полутора до трёх месяцев, в зависимости от количества фоновых задач и интеграций.

Разница не катастрофическая, и это главный практический вывод: если второй клиент под вопросом, отложить решение допустимо. Если он в планах на год — дешевле сделать сразу.

Про то, как это выглядит в готовом продукте, — в кейсе SaaS-платформы для онлайн-школы, где multi-tenant позволил запустить вторую школу на той же платформе. Про выбор между итерациями и фиксированным объёмом — в разборе продуктовой и проектной разработки.

Итог

Multi-tenant — это не галочка в списке технологий, а решение об изоляции данных с понятной ценой. Три модели различаются тем, где проходит граница между клиентами: разные базы, разные схемы или колонка в общей таблице. Чем сильнее изоляция, тем дороже эксплуатация.

Главная ошибка — считать, что переделка сводится к добавлению поля. Ломаются фоновые задачи, кеш, файлы, уникальные ограничения и интеграции, и именно они определяют реальную стоимость.

Если делаете SaaS — посмотрите услугу разработки SaaS-платформы: там про биллинг, подписки и white-label, из которых складывается остальная часть продукта.

Похожая задача в вашем бизнесе?

За 60 минут разберём вашу задачу, покажем архитектуру и оценим бюджет.