Когато започвахме Frizmo Platform, един от първите въпроси, които трябваше да решим, беше: "Как разделяме данните между клиентите?" Това звучи елементарно, но всъщност е едно от най-важните решения, защото то определя архитектурата на цялата система — от database schema-та до production deployment-а.
В тази статия ще разгледам трите основни подхода за multi-tenancy, плюсовете и минусите им, и кога кой работи най-добре. Това е резюме на проучването, което направихме преди да изберем модела за Frizmo Platform.
Подход 1: Database per tenant
Всеки tenant (клиент) получава собствена database. Изолацията е пълна — никаква възможност един tenant случайно да види данните на друг.
Кога работи
- Enterprise клиенти с регулаторни изисквания (HIPAA, GDPR, банков сектор)
- Tenant-и, които плащат премиум цена и очакват изолирана инфраструктура
- Случаи, в които всеки tenant има значително различен schema
Минуси
- Високи разходи — десетки бази данни вместо една
- Сложен deployment — миграциите трябва да се прилагат върху всички tenants
- По-трудно cross-tenant analytics (платформена статистика)
- Connection pooling става нетривиален
Подход 2: Schema per tenant
Един database, но всеки tenant има собствена schema (в Postgres) или собствен set от таблици. По-евтин от database-per-tenant, но запазва добра изолация.
Кога работи
- Среден брой tenants (десетки до стотици)
- Нужда от логическа изолация без infrastructure overhead
- Случаи, в които миграциите се прилагат еднакво за всички, но данните трябва да са разделени
Минуси
- При хиляди tenants Postgres започва да се чувства уморен (max_connections, schema каталога расте)
- Cross-tenant queries изискват UNION ALL върху всички schemas
- Backup стратегията става сложна
Подход 3: Shared schema, tenant_id колона
Една база, една schema, всяка таблица има tenant_id колона. Изолацията е логическа на ниво приложение и Row-Level Security (RLS).
Кога работи
- SaaS с много tenants и сравнително прост schema
- B2C платформи, в които изолацията е важна, но не е enterprise-grade
- Бюджетни constraints — този модел е най-евтиният от трите
- Frizmo Platform — точно този подход използваме
Минуси
- Изолацията е "soft" — една грешка в WHERE клауза може да доведе до data leak
- Изисква дисциплина в кодa — всеки query трябва да включва tenant_id
- RLS policies в Postgres са решение, но трябва да се конфигурират внимателно
Какво избрахме за Frizmo Platform
За Frizmo Platform избрахме shared schema подхода с задължителен tenant_id и RLS policies в Postgres. Решението беше базирано на:
- Очакван brой tenants — стотици до хиляди
- Schema е еднаква за всички tenants
- Cost-efficiency — една база е значително по-евтина от стотици
- Лесно cross-tenant analytics за вътрешни нужди (платформена статистика)
Заключение
Не съществува универсално правилен отговор. Изборът зависи от три фактора: брой tenants, регулаторни изисквания и budget. За повечето SaaS продукти shared schema с дисциплина в кода е правилният компромис. За enterprise клиенти с регулаторни нужди — database per tenant. Между тях schema-per-tenant покрива нишови случаи.
Грешка, която виждаме често: започване с грешния модел поради неправилна оценка на бъдещия мащаб. Миграцията между моделите е възможна, но е значителна работа. По-добре да се отдели време за решението сега, отколкото да се мигрира по-късно.