Ты разрабатываешь SaaS-продукт. У тебя уже есть первые клиенты — маленькие компании, которые платят за доступ. Всё идёт хорошо. Но ты знаешь: через полгода их станет 50, потом 500. И тут начинается самое интересное — как не устроить хаос, когда все клиенты будут использовать один и тот же сервер, одну базу данных, один код?
Если ты не продумал изоляцию данных с самого начала, то в один прекрасный день один клиент случайно увидит данные другого. Или твой сервер упадёт под нагрузкой, и все клиенты потеряют доступ. Или ты не сможешь добавить новый функционал, потому что он сломает старую логику для кого-то. Это не теория. Это реальность, в которую впадают 7 из 10 стартапов, которые начинают с «а давайте просто сделаем один общий сервер».
В этой статье я расскажу, как сделать multi-tenant SaaS так, чтобы:
- Данные одного клиента не смешивались с данными другого — даже если кто-то сломает код;
- Сервис не тормозил при росте клиентов;
- Ты мог легко добавлять новые функции, не ломая всё;
- И не потратил на это 6 месяцев и 200 тысяч долларов.
- Что такое multi-tenant SaaS и зачем тебе изоляция
- Три способа изоляции: плюсы, минусы, когда что использовать
- Как не сломать всё при переходе на изоляцию
- Частые ошибки — и как их избежать
- Что выбрать в зависимости от ситуации
- Как сделать это правильно — практические рекомендации
- Итог: что делать прямо сейчас
Что такое multi-tenant SaaS и зачем тебе изоляция
Multi-tenant — это когда один экземпляр твоего приложения обслуживает сразу много клиентов («тенантов»). Это выгодно: ты не развертываешь отдельный сервер для каждого клиента. Это экономит ресурсы, упрощает обновления и снижает стоимость поддержки.
Но есть ловушка: если ты не изолируешь данные, то всё, что делает один клиент, может повлиять на другого. Допустим, у тебя есть CRM-система. Клиент А — агентство недвижимости. Клиент Б — маленький магазин. Если ты храните все данные в одной таблице clients без фильтрации по tenant_id, то:
- Злоумышленник может подобрать ID и вытащить чужие данные;
- Ошибки в запросах — и ты случайно удалишь контакты из двух компаний;
- Когда клиент А захочет кастомный отчёт, ты не сможешь его сделать, не сломав отчёт для клиента Б.
Изоляция — это не про «хорошо бы». Это про юридическую безопасность, репутацию и выживание бизнеса. GDPR, CCPA, ФЗ-152 — все требуют, чтобы данные одного клиента не попадали к другому. Нарушение — это штрафы, иски, потеря клиентов. И ты не сможешь продать продукт крупной компании, если не докажешь, что изоляция есть.
Три способа изоляции: плюсы, минусы, когда что использовать
Существует три основных подхода к изоляции данных. Ни один из них не идеален. Выбор зависит от масштаба, бюджета и требований клиентов.
| Подход | Как работает | Плюсы | Минусы | Когда подходит |
|---|---|---|---|---|
| Общая база, общая схема | Все клиенты в одной таблице. Каждая запись имеет поле tenant_id. Все запросы фильтруются по нему. | Просто в разработке. Легко обновлять. Мало затрат на хостинг. | Один баг — и все клиенты страдают. Сложно кастомизировать. Риск утечки, если забыл фильтр. | Стартап с 1–50 клиентами. Нет требований к кастомизации. Нет чувствительных данных. |
| Общая база, отдельные схемы | Одна БД, но для каждого клиента — отдельная схема (в PostgreSQL — schema, в MySQL — database). Код работает с динамическим выбором схемы. | Хорошая изоляция. Можно кастомизировать структуру для каждого клиента. Легко бэкапить по клиентам. | Сложнее миграции. Труднее делать аналитику по всем клиентам. Нужно больше памяти. | 50–500 клиентов. Есть клиенты с особыми требованиями к структуре данных. Нужна гибкость. |
| Отдельные базы | Каждому клиенту — отдельная база данных на отдельном сервере или в отдельном контейнере. | Полная изоляция. Можно масштабировать по клиентам. Легко переносить клиентов между серверами. Безопасно. | Сложно управлять. Высокие затраты на хостинг. Миграции — кошмар. Требует автоматизации. | 500+ клиентов. Клиенты — корпорации с жёсткими требованиями к безопасности. Данные — финансовые, медицинские, юридические. |
Самый частый выбор — первый вариант. Он работает. Пока клиентов мало. Но если ты планируешь расти — не останавливайся на нём. Это как строить дом на песке и надеяться, что ветер не подует.
Как не сломать всё при переходе на изоляцию
Ты уже запустил продукт с общим подходом. Клиенты есть. И ты понял: пора менять архитектуру. Это страшно. Но можно сделать это без катастрофы.
- Добавь tenant_id везде. Даже если сейчас всё в одной таблице — начни с этого. Добавь поле в каждую таблицу, где есть данные клиента. Не жди «когда будет время» — делай прямо сейчас.
- Запусти фильтрацию на уровне приложения. Всё, что обращается к БД — должно автоматически добавлять
WHERE tenant_id = current_tenant. Не доверяй разработчикам — сделай это в ORM или на уровне репозитория. Например, в Django — через middleware. В Node.js — через интерцепторы запросов. - Проверь все старые запросы. Найди все места, где ты используешь
SELECT * FROM usersбез фильтрации. Добавь тесты, которые проверяют, что никто не может получить данные другого клиента. - Сделай миграцию постепенно. Не переноси всех клиентов сразу. Выбери одного-двух «добровольцев» — тех, кто согласен на тест. Перенеси их данные в отдельную схему. Проверь, всё ли работает. Потом — ещё двух. И так до 10%. Потом — до 50%. Потом — до 100%.
- Автоматизируй развертывание. Если ты перешёл на отдельные схемы или базы — тебе нужно, чтобы при регистрации нового клиента автоматически создавалась схема, мигрировались таблицы, настраивались права. Используй Terraform, Ansible или просто скрипты на Python/Node.js. Не делай это вручную.
Не пытайся всё переделать за неделю. Ты не спасёшь мир за 7 дней. Ты спасёшь бизнес за 3 месяца — если будешь двигаться осторожно.
Частые ошибки — и как их избежать
Я видел, как падали продукты. Вот что ломает multi-tenant SaaS чаще всего:
- Забыли фильтр в одном запросе. Случайно написали
SELECT * FROM invoices— и один клиент увидел все счета. Это случается, когда кто-то пишет «быстрый фикс» и не проверяет контекст. - Кеширование без учёта тенанта. Ты кешируешь результат запроса по ключу
user_id, но не поtenant_id. Один пользователь видит чужие данные из кеша. Решение: всегда включайtenant_idв ключ кеша. - Используют общие последовательности ID. Например, все клиенты используют одну последовательность ID для заказов. Один клиент видит, что у другого заказ №12345 — и понимает, что у него 12 тысяч заказов. Это раскрывает масштаб бизнеса. Решение: используй UUID или генерируй ID в пределах тенанта.
- Не проверяют права доступа на уровне API. Допустим, API принимает
/api/invoices/123. Если ты не проверяешь, что этот invoice принадлежит текущему тенанту — злоумышленник может перебирать ID. Решение: всегда проверяй принадлежность в контроллере, а не только в UI. - Слишком рано перешли на отдельные базы. Начали с 10 клиентов и сделали по базе на каждого. В итоге — 100 БД, 30 серверов, и ты тратишь 80% времени на поддержку инфраструктуры, а не на продукт.
Проверяй всё. Даже если кажется, что «это же очевидно». Всё, что работает с данными — должно быть протестировано на изоляцию. Добавь в CI/CD тест, который имитирует запрос от одного клиента к данным другого. Если он проходит — ты в опасности.
Что выбрать в зависимости от ситуации
Вот как принимать решение, если ты ещё не начал:
- Если у тебя 1–20 клиентов, нет требований к безопасности, и ты хочешь запустить быстро — используй общую базу с tenant_id. Это нормально. Не стыдись. Многие успешные SaaS-продукты начинали так. Но добавь фильтрацию везде. И запланируй миграцию на схемы через 6 месяцев.
- Если клиентов 20–300, и ты хочешь дать им возможность кастомизировать поля, отчёты, интеграции — переходи на отдельные схемы. Это даёт гибкость. Ты можешь добавить поле
custom_field_1для одного клиента, не трогая других. Это стоит больше, чем общий подход, но меньше, чем отдельные базы. - Если клиенты — банки, госорганы, медицинские учреждения, или ты планируешь продавать за $1000+/месяц — сразу иди на отдельные базы. Это не «перестраховка». Это требование. Большинство корпоративных клиентов потребуют аудит безопасности. И если ты не сможешь показать, что данные физически разделены — они не купят.
Если ты не уверен — начни с общего подхода. Но сделай так, чтобы миграция на схемы была возможна через 3–6 месяцев. Заложи это в архитектуру с самого начала.
Как сделать это правильно — практические рекомендации
Вот что реально работает, если ты не хочешь спать ночами, боясь утечки данных:
- Создай «тенант-контекст». В каждом HTTP-запросе определяй, кто клиент (через JWT, хедер, домен). Сохраняй его в контексте запроса. Используй этот контекст везде — в ORM, в логах, в бэкапах.
- Не пиши SQL-запросы вручную без фильтрации. Используй ORM с поддержкой tenant. Например, в Django —
django-tenants, в Ruby on Rails —acts_as_tenant. Если пишешь на чистом SQL — напиши обёртку, которая автоматически добавляетWHERE tenant_id = ?. - Сделай мониторинг на утечки. Запиши в логи все запросы, где
tenant_idотсутствует. Настрой алерт, если такой запрос появляется. Это твой «детектор утечек». - Проводи тесты на изоляцию еженедельно. Создай тест, который делает запрос от клиента A к данным клиента B. Если он проходит — ты в опасности. Это должен быть автоматический тест в CI/CD.
- Используй отдельные базы только тогда, когда действительно нужно. Не потому что «все так делают». Если твой клиент — маленький магазин, и ты не хранишь персональные данные — тебе не нужны отдельные базы. Это перерасход.
И самое главное: не доверяй коду. Доверяй проверкам. Даже если ты уверен, что фильтр везде стоит — проверь. Потому что кто-то когда-нибудь забудет. И это будет не ты. А новичок в команде. Или ты сам — через год, когда уже не помнишь, как всё устроено.
Итог: что делать прямо сейчас
Если ты ещё не запустил продукт — сделай так:
- Добавь
tenant_idв каждую таблицу, где есть данные клиента. - Настрой ORM или слой доступа к БД, чтобы он автоматически фильтровал по
tenant_id. - Напиши тест, который проверяет, что один клиент не может получить данные другого.
- Запусти продукт. Собирай обратную связь.
Если ты уже запустил — сделай так:
- Найди все места, где нет
tenant_idв запросах. Исправь их. - Добавь мониторинг на отсутствующие фильтры.
- Сделай план миграции на отдельные схемы — на 6–12 месяцев.
- Начни с одного клиента. Перенеси его данные. Проверь. Потом — ещё одного.
Ты не должен делать всё идеально с первого раза. Но ты должен делать так, чтобы в любой момент можно было исправить ошибку — без потери клиентов, без штрафов, без паники.
Multi-tenant — это не про архитектурный шик. Это про то, чтобы твой продукт не стал причиной катастрофы для твоих клиентов. И чтобы ты не потерял всё из-за одной ошибки в SQL-запросе.
Начни с малого. Проверь фильтр. Добавь тест. Запусти. И не жди, пока кто-то украдёт данные. Сделай это до того, как это сделает кто-то другой.
Информация в этой статье носит ознакомительный характер. Выбор архитектуры, настройка безопасности и соответствие требованиям законодательства требуют консультации с профильными специалистами — юристами, инженерами безопасности и аудиторами.
