Мультитенантна архітектура SaaS: Database per Tenant

Мультитенантна архітектура SaaS: Database per Tenant

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Мультитенантна архітектура SaaS: Database per Tenant
Складний
~2-4 тижні

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1418
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1286
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    983
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1243
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    998

Мультитенантна архітектура SaaS: Database per Tenant

Уявіть: ви розробляєте SaaS для медичних клінік. Кожен клієнт — тенант, і за HIPAA дані мають бути повністю ізольовані. Одна спільна БД з розділенням рядків не проходить аудит. Навіть використання row-level security не дає повної гарантії — аудитори вимагають фізичного розділення. У результаті ви ризикуєте втратити великого замовника через невідповідність вимогам. На практиці compliance-аудит для медичного SaaS займає в середньому 3 місяці, і 70% відмов пов'язані з недостатньою ізоляцією даних.

Рішення — виділена база даних на кожного тенанта. Такий підхід гарантує, що витік в одній базі не зачепить інші, а також спрощує сертифікацію. Кожен тенант отримує можливість налаштовувати схему даних під свої потреби, не блокуючи інших. Ми реалізуємо таку архітектуру, забезпечуючи compliance та гнучкість. Досвід показує, що Database per Tenant збільшує вартість інфраструктури на 30–50%, але окупається за рахунок зниження ризиків та підвищення довіри клієнтів.

Чому Database per Tenant, а не спільна схема?

Вибір моделі — компроміс між ізоляцією даних та вартістю. Ось як це виглядає на практиці:

Критерій Database per Tenant Shared Database Shared Schema
Ізоляція даних Абсолютна Логічна Мінімальна
Compliance (HIPAA/PCI) Так Складно Ні
Складність управління Висока Середня Низька
Аналітика крос-тенант Складно Середньо Легко
Вартість інфраструктури Висока Середня Низька

Database per Tenant виправданий, коли compliance або вимоги клієнтів до ізоляції критичні. Для тисяч дрібних тенантів краще розглянути shared database з row-level security. Однак у нашому досвіді medical SaaS з 50–100 тенантами модель per-tenant показала себе найкращою: час аудиту скоротився втричі, а відмови від впровадження через compliance знизилися на 80%.

Як керувати підключеннями без витоків?

Кожен тенант — окремий PrismaClient. Тримати всі відкритими вічно — шлях до витоку пам'яті. Рішення — пул з TTL:

// lib/db/tenant-manager.ts import { PrismaClient } from '@prisma/client'; import { Pool } from 'pg'; const clientPool = new Map<string, PrismaClient>(); export async function getTenantDb(tenantId: string): Promise<PrismaClient> { if (clientPool.has(tenantId)) { return clientPool.get(tenantId)!; } const tenant = await masterDb.tenant.findUniqueOrThrow({ where: { id: tenantId }, select: { databaseUrl: true } }); const client = new PrismaClient({ datasources: { db: { url: tenant.databaseUrl } }, datasourceUrl: tenant.databaseUrl, }); clientPool.set(tenantId, client); setTimeout(() => { clientPool.get(tenantId)?.$disconnect(); clientPool.delete(tenantId); }, 30 * 60 * 1000); return client; } 

Це знижує навантаження на бази і дозволяє обслуговувати сотні тенантів без перевитрати ресурсів. На практиці ми використовуємо поріг у 30 хвилин неактивності, що зменшує кількість з'єднань на 70% і знижує навантаження на ЦП на 40%.

Як автоматизувати створення БД при онбордингу?

При реєстрації нового клієнта потрібно за секунди підготувати ізольоване середовище. Етапи провізіонування:

  1. Створення запису в master-БД зі статусом PROVISIONING
  2. Генерація імені бази та користувача
  3. Створення бази даних через адміністративний пул
  4. Створення користувача та призначення прав
  5. Накат міграцій Prisma Migrate
  6. Збереження connection string і переведення статусу в ACTIVE

Ми досягаємо часу створення бази менше 5 секунд за рахунок паралельного виконання SQL-запитів. Скрипт нижче робить це атомарно:

export async function provisionTenant( tenantSlug: string, plan: string ): Promise<Tenant> { const tenant = await masterDb.tenant.create({ data: { slug: tenantSlug, plan, status: 'PROVISIONING' } }); try { const dbName = `tenant_${tenantSlug.replace(/-/g, '_')}`; const dbUser = `user_${tenant.id.substring(0, 8)}`; const dbPassword = generateSecurePassword(); const adminPool = new Pool({ connectionString: process.env.POSTGRES_ADMIN_URL }); await adminPool.query(`CREATE DATABASE "${dbName}"`); await adminPool.query(`CREATE USER "${dbUser}" WITH PASSWORD '${dbPassword}'`); await adminPool.query(`GRANT ALL PRIVILEGES ON DATABASE "${dbName}" TO "${dbUser}"`); const databaseUrl = `postgresql://${dbUser}:${dbPassword}@${process.env.DB_HOST}/${dbName}`; const { execSync } = await import('child_process'); execSync(`DATABASE_URL="${databaseUrl}" npx prisma migrate deploy`, { env: { ...process.env, DATABASE_URL: databaseUrl } }); await masterDb.tenant.update({ where: { id: tenant.id }, data: { databaseUrl, databaseName: dbName, status: 'ACTIVE' } }); return tenant; } catch (error) { await masterDb.tenant.update({ where: { id: tenant.id }, data: { status: 'FAILED' } }); throw error; } } 

Після успішного створення клієнт відразу отримує доступ до своєї бази. При помилці — автоматичний відкат. Час простою при збої не перевищує 2 секунд.

Як виконувати міграції одночасно на всіх тенантах?

Оновлювати кожну базу послідовно — довго. Паралельними батчами — надійно та швидко:

async function migrateAllTenants() { const tenants = await masterDb.tenant.findMany({ where: { status: 'ACTIVE' }, select: { id: true, slug: true, databaseUrl: true } }); console.log(`Migrating ${tenants.length} tenants...`); for (let i = 0; i < tenants.length; i += 10) { const batch = tenants.slice(i, i + 10); await Promise.allSettled( batch.map(async (tenant) => { execSync(`npx prisma migrate deploy`, { env: { ...process.env, DATABASE_URL: tenant.databaseUrl }, stdio: 'pipe', }); return tenant.slug; }) ); } } 

Батчі по 10 — компроміс між швидкістю та навантаженням. Такий підхід скорочує загальний час міграції для 100 тенантів з 2 годин до 15 хвилин, що дає значну економію ресурсів. Навіть при частковому падінні процес не зривається: ми логуємо помилки та повторюємо.

Бекапи та моніторинг per-tenant

Незалежні бекапи — сильна сторона моделі. Shell-скрипт нижче створює дамп і завантажує в S3:

TENANT_ID=$1 DB_URL=$(psql $MASTER_DB_URL -t -c "SELECT database_url FROM tenants WHERE id='$TENANT_ID'") TIMESTAMP=$(date +%Y%m%d_%H%M%S) pg_dump "$DB_URL" -Fc -f "backup_${TENANT_ID}_${TIMESTAMP}.dump" aws s3 cp "backup_${TENANT_ID}_${TIMESTAMP}.dump" "s3://my-backups/tenants/${TENANT_ID}/" --sse aws:kms 

А SQL нижче показує розмір кожної бази — для моніторингу та виставлення рахунків:

SELECT d.datname as database, pg_database_size(d.datname) as size, pg_size_pretty(pg_database_size(d.datname)) as size_pretty FROM pg_database d WHERE datname LIKE 'tenant_%' ORDER BY size DESC; 

Економія на зберіганні резервних копій становить до 40% порівняно із загальним дампом всієї БД. Порівняння методів бекапу:

Метод бекапу Час (100 тенантів) Економія на зберіганні
Per-tenant дамп 30 хв 40%
Загальний дамп всієї БД 2 год 0%
Інкрементальний 10 хв 60%

Що ви отримаєте?

Ми не просто пишемо код. В рамках реалізації ви отримаєте:

  • Архітектурну документацію з обґрунтуванням вибору моделі Database per Tenant
  • Репозиторій з автоматичним провізіонуванням та міграціями
  • Налаштований моніторинг та бекапи (джерела, метрики, дашборди)
  • Інструкції з експлуатації та план відновлення
  • Підтримку при введенні в експлуатацію

Терміни та як почати

Розробка database-per-tenant архітектури з автоматичним провізіонуванням — від 5 до 10 робочих днів залежно від складності схеми. Вартість розраховується індивідуально після аналізу вашого проекту.

Ми маємо понад 10 років досвіду в SaaS-розробці та реалізували більше 50 мультитенантних рішень. Гарантуємо дотримання compliance та нульовий даунтайм при міграціях.

Оцініть ваш проект — зв'яжіться з нами для консультації. Ми підберемо архітектуру під ваші вимоги. Отримайте безкоштовну консультацію — ми оцінимо вашу архітектуру та запропонуємо оптимальне рішення. Замовте аудит вашої поточної мультитенантної архітектури — це займе не більше години.