Розробка мультитенантної AI-платформи (SaaS) для B2B-клієнтів
Мультитенантна AI SaaS - це архітектурний патерн, де єдина кодова база обслуговує безліч B2B-клієнтів (тенантів) з ізоляцією даних, кастомізацією та незалежним білінгом. Правильна архітектура визначає масштабованість та безпеку платформи.
Моделі мультитенантності
Shared Database, Shared Schema (найекономічніша): Усі тенанти в одній БД, розмежування через 'tenant_id' колонку. Простота операцій, складність ізоляції.
Shared Database, Separate Schema: Кожен тенант отримує окрему схему PostgreSQL. Найкраща ізоляція, можливість per-tenant індексів.
Separate Database per Tenant: Кожен тенант – окрема база. Максимальна ізоляція, складність операцій при 1000+ тенантах.
Для AI-платформи з ML-моделями оптимально: Shared DB + Separate Schema ** для транзакційних даних + окремі S3 prefixes для ML артефактів кожного тенанта.
Row-Level Security у PostgreSQL
-- Включение RLS для изоляции данных тенантов
ALTER TABLE predictions ENABLE ROW LEVEL SECURITY;
-- Политика: каждый тенант видит только свои данные
CREATE POLICY tenant_isolation ON predictions
USING (tenant_id = current_setting('app.current_tenant_id')::UUID);
-- Установка tenant context для каждого соединения
-- (выполняется при начале сессии)
SET LOCAL app.current_tenant_id = '550e8400-e29b-41d4-a716-446655440000';
# FastAPI middleware для установки tenant context
@app.middleware("http")
async def tenant_context_middleware(request: Request, call_next):
tenant_id = await resolve_tenant(request)
request.state.tenant_id = tenant_id
async with db.acquire() as conn:
# Установка tenant context для всех запросов в рамках соединения
await conn.execute(
f"SET LOCAL app.current_tenant_id = '{tenant_id}'"
)
request.state.db_conn = conn
response = await call_next(request)
return response
Tenant-specific AI конфігурація
@dataclass
class TenantAIConfig:
tenant_id: str
# Разрешённые модели
allowed_models: list[str]
# Кастомные системные промпты (branding)
system_prompt_override: str = None
# Лимиты использования
monthly_token_limit: int = 1_000_000
concurrent_request_limit: int = 10
# Fine-tuned модели тенанта
custom_models: list[str] = None
# Data retention
prediction_log_retention_days: int = 90
# Compliance settings
pii_detection_enabled: bool = True
audit_log_enabled: bool = True
class TenantAwareInferenceService:
async def predict(self, tenant_id: str, model_name: str,
inputs: dict) -> dict:
config = await self.get_tenant_config(tenant_id)
# Проверка разрешений
if model_name not in config.allowed_models:
raise PermissionError(f"Model '{model_name}' not allowed for this tenant")
# Проверка rate limits
if not await self.rate_limiter.check(tenant_id, config.concurrent_request_limit):
raise RateLimitError("Concurrent request limit exceeded")
# Применение tenant-specific промпта
if config.system_prompt_override and 'system' in inputs:
inputs['system'] = config.system_prompt_override + "\n\n" + inputs['system']
# PII detection перед отправкой в модель
if config.pii_detection_enabled:
inputs = await self.pii_detector.redact(inputs)
result = await self.inference_engine.run(model_name, inputs)
# Логирование с изоляцией по тенанту
await self.audit_log.record(tenant_id, model_name, inputs, result)
return result
Onboarding нового тенанта
class TenantOnboardingService:
async def provision_tenant(self, signup_data: dict) -> Tenant:
tenant = await self.db.create_tenant(signup_data)
# Создание изолированной схемы данных
await self.db_manager.create_schema(tenant.id)
await self.db_manager.run_migrations(tenant.id)
# Создание S3 prefixes
await self.storage.create_tenant_prefix(tenant.id)
# Дефолтная конфигурация
await self.config_store.create_default_config(tenant.id)
# Выдача API ключей
api_key = await self.auth.create_api_key(tenant.id, scope="all")
# Начальное письмо с инструкциями
await self.email.send_welcome(tenant, api_key)
return tenant, api_key
Ізоляція ML-моделей за тенантами
Тенанти можуть fine-tune базові моделі на своїх даних. Кожна fine-tuned модель ізольована – доступна тільки тому тенанту, який її створив:
# Fine-tuning endpoint
@app.post("/v1/fine-tuning/jobs")
async def create_fine_tuning_job(request: FineTuningRequest,
tenant_id = Depends(get_tenant)):
# Данные тенанта → его fine-tuned модель
job = await fine_tuning_service.create_job(
tenant_id=tenant_id,
base_model=request.model,
training_file=request.training_file, # Файл в tenant-specific S3 prefix
)
return job
Термін розробки мультитенантної AI SaaS: 3-5 місяців залежно від кількості тенантів, вимог до ізоляції та складності AI-функціональності.







