Створення багатокористувацького SaaS: робочі простори, ролі, білінг та ізоляція

Як спроєктувати робочі простори, рольовий доступ, тарифи білінгу та ізоляцію клієнтів для масштабованого SaaS. Практична архітектура від DigiForge.

DFКоманда DigiForgeJul 20, 20268 хв читання
Абстрактні сяючі взаємопов'язані блоки на темному фоні, що символізують архітектуру багатокористувацького SaaS.

Мультитенантне SaaS — це архітектура за замовчуванням для будь-якої B2B-платформи, яка планує зростати понад кілька клієнтів. Однак диявол криється в деталях: те, як ви моделюєте робочі простори, призначаєте ролі, структуруєте білінг та ізолюєте клієнтів, визначає, чи масштабуватиметься ваша платформа гладко, чи звалиться під складністю. У DigiForge ми створювали та перебудовували такі системи для десятків SaaS-продуктів. Ось що ми дізналися.

Робочі простори: Основний елемент організації

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

Ключові архітектурні рішення:

  • Ієрархічний чи плаский? Деяким платформам потрібні робочі простори всередині робочих просторів (наприклад, підприємство з кількома відділами). Ми рекомендуємо дворівневу ієрархію: організація (суб'єкт білінгу) та робочий простір (командний підрозділ). Уникайте глибшого вкладення, якщо це не абсолютно необхідно — це ускладнює успадкування ролей та доступ до даних.
  • Унікальні ідентифікатори: Використовуйте зручний для читання слаг (наприклад, acme або acme-marketing) для робочого простору в URL, але завжди покладайтеся на UUID всередині системи. Слаги можуть змінюватися; UUID — ні.
  • М'яке видалення з пільговим періодом: Видалення робочого простору — це радикальна дія. Запровадьте 30-денне м'яке видалення, щоб користувачі могли відновити дані. Припиніть білінг негайно, але зберігайте дані до закінчення пільгового періоду.

Коли новий користувач реєструється, продумайте процес онбордингу. Чи варто спочатку створити робочий простір, чи дозволити досліджувати пісочницю? Ми віддаємо перевагу керованому процесу, де користувач створює організацію, потім свій перший робочий простір і одразу отримує пропозицію запросити колег. Це зменшує тертя та задає очікування, що платформа є колаборативною.

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

Ролі та дозволи: деталізовані, але не надто

Контроль доступу на основі ролей (RBAC) є галузевим стандартом, але ступінь деталізації має значення. У DigiForge ми зазвичай починаємо з трьох вбудованих ролей — Адміністратор, Учасник, Спостерігач — і дозволяємо створювати власні ролі для розширених планів. Адміністратор має повний контроль над робочим простором, Учасники можуть створювати та редагувати більшість ресурсів, а Спостерігачі можуть лише читати.

Складність виникає з областю дії дозволів. За замовчуванням дозволи мають бути обмежені робочим простором, але можуть знадобитися дозволи на рівні організації (наприклад, керування оплатою) або навіть доступ на читання між робочими просторами для консолідованої звітності. Моделюйте дозволи як набір пар action:resource і призначайте їх ролям. Зберігайте призначення в таблиці зв'язків: (workspace_id, user_id, role_id).

Порада від професіоналів: Не покладайтеся лише на перевірку дозволів на рівні застосунку. Переносьте якомога більше логіки прав доступу до вашої бази даних, використовуючи захист на рівні рядків (RLS) або механізм політик, як-от OPA. Це зменшує ймовірність того, що помилка у веб-шарі призведе до розкриття чужих даних.

Один із патернів, який добре себе зарекомендував, — кешувати роль користувача в токені сесії (JWT), а не робити запит до бази даних при кожному зверненні. Але будьте обережні: якщо ви кешуєте ролі в JWT, вам потрібен механізм для анулювання токенів при зміні ролі (наприклад, короткий термін дії токена або чорний список).

Також варто подумати про успадкування ролей: чи повинен адміністратор організації автоматично мати права адміністратора у всіх робочих просторах? Наше правило: ролі організації задають верхню межу, але ролі робочих просторів можуть бути більш обмежувальними. Наприклад, адміністратор організації може отримати доступ до будь-якого робочого простору, але адміністратор робочого простору не може переглядати платіжні дані.

Білінг і моделі ціноутворення: метадані, а не бізнес-логіка

Білінг — це те, де мультитенантність стає реальною. Ваша модель ціноутворення (за місце, за робочий простір, на основі використання або рівнева) має бути відображена у вашій моделі даних, але система білінгу повинна бути відокремлена від основного застосунку. Використовуйте стороннього провайдера білінгу (Stripe, Recurly, Chargebee) і зберігайте в базі даних лише ID підписки та ID плану.

Ми рекомендуємо наступний підхід до бази даних:

  1. Таблиця plans, яка визначає слаг плану, ціну та прапорці функцій (наприклад, max_users, storage_gb, api_rate_limit).
  2. Таблиця organizations, яка має current_plan_id та billing_provider_subscription_id. Зв'яжіть організації з робочими просторами через допоміжну таблицю.
  3. Таблиця features (або проста колонка JSON), яка зберігає перевизначення. Наприклад, якщо клієнт домовився про індивідуальну ціну, перевизначте ціну плану на рівні організації.

Найскладніше — обмежити доступ на основі плану. У вас є два варіанти: застосовувати обмеження в додатку (перевіряти max_users перед запрошенням) або через кількість рядків у базі даних та тригери. Ми віддаємо перевагу обмеженням на рівні додатку, оскільки це дає кращі повідомлення про помилки для користувача, але завжди додаємо нічне завдання узгодження, яке позначає організації, що перевищують ліміти.

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

Один урок з окопів: ніколи не допускайте, щоб збої в оплаті призводили до втрати даних. Якщо платіж не вдався, погіршуйте якість обслуговування поступово (наприклад, обмежте операції запису), але не видаляйте дані. Ваш клієнт заплатить — зрештою.

Ізоляція клієнтів: спільне використання проти окремих баз

Ізоляція — це найважливіше архітектурне рішення. Стандартний компроміс — між спільною базою даних (одна база для всіх клієнтів, з колонкою tenant_id у кожній таблиці) та окремою базою на клієнта (кожен робочий простір отримує власну базу). Ми випробували обидва підходи і зупинилися на гібридному для більшості проєктів.

  • Спільна з суворим RLS: Підходить для малих та середніх клієнтів (до 10 000 користувачів кожен). Безпека на рівні рядків вбудована в Postgres, і ми використовуємо змінну сесії (app.tenant_id) для фільтрації кожного запиту. Це найпростіший варіант для експлуатації та оновлення.
  • Окрема база на клієнта: Необхідна, коли клієнти вимагають суворої відповідності (HIPAA, SOC 2, GDPR щодо розташування даних) або коли додаток має високе навантаження введення-виведення на клієнта. Операційні витрати реальні — міграції схем потрібно застосовувати до сотень баз, але такі інструменти, як Flyway та автоматизований CI, роблять це керованим.
  • Окрема схема на клієнта: Компромісний варіант з використанням окремих схем в одній базі даних. Він забезпечує більшу ізоляцію, ніж спільна таблиця, але менші операційні витрати, ніж повні бази даних. Ми використовуємо це для наших тарифів нижчого рівня і переводимо клієнтів на окрему базу, якщо це необхідно.

Незалежно від стратегії ізоляції, ніколи не дозволяйте прямий доступ до бази даних з клієнта. Завжди маршрутизуйте через API-шар, який забезпечує ідентифікацію клієнта. І заради вашої чергової команди: ніколи, ні за яких обставин не використовуйте tenant_id в URL без перевірки, що автентифікований користувач належить цьому клієнту.

Міграція даних між рівнями ізоляції — реальність. Наприклад, коли клієнт переростає спільну базу даних, може знадобитися перенести його на виділену базу. Плануйте це заздалегідь: напишіть скрипт міграції, який експортує та імпортує дані, і протестуйте його на даних, наближених до реальних. Він має виконуватися без простою, використовуючи підхід blue-green.

Автоматизоване налаштування: нехай машина це робить

Ручне створення нових клієнтів може працювати для перших десяти замовників, але не масштабується. Як підкреслює нещодавній патент ContractorHUB, реалізація без втручання людини є ключовою відмінністю для багатокористувацького SaaS [1]. Ми створили робочі процеси налаштування, які автоматизують усе: від створення бази даних (або клонування схеми) до заповнення початковими даними та надсилання вітальних листів.

Типовий конвеєр автоматизованого налаштування:

  1. Користувач реєструється, створює організацію та обирає тариф.
  2. Вебхук від вашого платіжного провайдера запускає завдання налаштування (наприклад, серверну функцію або завдання Kubernetes).
  3. Завдання створює рівень ізоляції клієнта (схему або базу даних), виконує початкові міграції та заповнює ролі та налаштування за замовчуванням.
  4. Друге завдання надсилає листа з інструкціями для входу та наступними кроками.
  5. Користувача перенаправляють до нового робочого простору — повністю функціонального — за лічені секунди.

Ідемпотентність тут є обов'язковою. Якщо завдання налаштування збійне посередині, його має бути безпечно повторити. Ми обгортаємо весь процес у скінченний автомат зі стовпцем provisioning_status у рядку організації: pending → creating → active → failed. Невдалі стани потрапляють до черги мертвих листів для втручання людини.

Не забудьте підготувати допоміжну інфраструктуру: DNS-записи для власних доменів, прогрівачі CDN-кешу, ліміти швидкості API на орендаря та сповіщення моніторингу. Автоматизуйте все, що можна заскриптувати, адже ручні кроки будуть забуті під тиском.

Висновок: Мислення багатоорендарної системи

Багатоорендарність — це не те, що додають після запуску. Вона має визначати вашу модель даних, контроль доступу, інтеграцію білінгу та стратегію розгортання з першого дня. Хороша новина: якщо ви правильно реалізуєте ці чотири стовпи — робочі простори, ролі, білінг та ізоляцію — решта вашого SaaS стане значно простішою у створенні та підтримці.

Кожен SaaS унікальний, але описані вище патерни добре зарекомендували себе в різних галузях. Чи ви тільки починаєте свій MVP, чи масштабуєтеся до тисяч орендарів, ми закликаємо вас глибоко обміркувати ці рішення. А якщо вам потрібен свіжий погляд на вашу архітектуру, ми завжди раді переглянути її.

#багатокористувацький#saas#робочі-простори#ролі#білінг#ізоляція#провізіонінг
DF

Команда DigiForge

Інженерна команда DigiForge — створюємо сучасні вебсайти, модулі та автоматизацію, а також пишемо про мистецтво випуску швидких та надійних вебпродуктів.

Обговорімо

Маєте проєкт
на думці?

Розкажіть нам, що ви створюєте — ми розробимо чіткий план і підберемо правильний підхід для вашого продукту.

Розпочати проєкт