بناء SaaS متعدد المستأجرين: مساحات العمل، الأدوار، الفوترة، والعزل
كيفية تصميم مساحات العمل، الوصول القائم على الأدوار، مستويات الفوترة، وعزل المستأجرين لـ SaaS قابل للتوسع. بنية عملية من DigiForge.

تُعد بنية SaaS متعددة المستأجرين (Multi-tenant) هي البنية الافتراضية لأي منصة B2B تتطلع إلى النمو بما يتجاوز حفنة من العملاء. لكن الشيطان يكمن في التفاصيل: كيف تصمم مساحات العمل، وتخصص الأدوار، وتبني نظام الفوترة، وتعزل المستأجرين — كل ذلك يحدد ما إذا كانت منصتك ستتوسع بسلاسة أم ستنهار تحت التعقيد. في DigiForge، قمنا ببناء وإعادة بناء هذه الأنظمة عبر عشرات منتجات SaaS. إليك ما تعلمناه.
مساحات العمل: الوحدة الأساسية للتنظيم
مساحة العمل هي حاوية منطقية تجمع المستخدمين والبيانات والإعدادات لعميل واحد (أو فريق داخل عميل). لاحظنا أن بعض الفرق تخلط بين مساحات العمل وحسابات الفوترة أو حتى المشاريع — لا تفعل ذلك. اجعل مساحة العمل هي النطاق الأساسي للمستأجر، ثم أضف مفاهيم أخرى فوقها.
قرارات التصميم الرئيسية:
- هرمية أم مسطحة؟ تحتاج بعض المنصات إلى مساحات عمل داخل مساحات عمل (مثل مؤسسة بها أقسام متعددة). نوصي بتسلسل هرمي من مستويين: المؤسسة (كيان الفوترة) ومساحة العمل (وحدة الفريق). تجنب التداخل الأعمق إلا إذا كان ضروريًا للغاية — فهو يعقد توارث الأدوار والوصول إلى البيانات.
- معرفات فريدة: استخدم معرفًا مقروءًا بشريًا (مثل
acmeأوacme-marketing) لمساحة العمل في عناوين URL، ولكن اعتمد دائمًا على UUID داخليًا. يمكن أن تتغير المعرفات المقروءة؛ بينما يجب ألا تتغير UUIDs. - حذف ناعم مع فترة سماح: حذف مساحة العمل هو إجراء جذري. قم بتنفيذ حذف ناعم لمدة 30 يومًا ليتمكن المستخدمون من استعادة البيانات. أوقف الفوترة فورًا ولكن احتفظ بالبيانات حتى انتهاء فترة السماح.
عند تسجيل مستخدم جديد، فكر في تدفق الإعداد الأولي. هل يجب عليه إنشاء مساحة عمل أولاً، أم يمكنه استكشاف بيئة اختبارية؟ نحن نفضل تدفقًا موجهًا حيث يقوم المستخدم بإنشاء مؤسسة، ثم أول مساحة عمل له، ويتم توجيهه فورًا لدعوة زملائه. هذا يقلل من الاحتكاك ويضع التوقعات بأن المنصة تعاونية.
من الأخطاء الشائعة ربط خطط الفوترة مباشرة بمساحات العمل. بدلاً من ذلك، اربط الفوترة بمؤسسة تحتوي على مساحة عمل واحدة أو أكثر. هذا يسمح للمؤسسات بالحصول على فاتورة واحدة مع إعطاء كل فريق مساحة العمل الخاصة به.
الأدوار والأذونات: دقيقة ولكن ليست مفرطة
التحكم في الوصول القائم على الأدوار (RBAC) هو المعيار الصناعي، لكن درجة التفصيل مهمة. في DigiForge، نبدأ عادةً بثلاثة أدوار مدمجة—المسؤول، العضو، المشاهد—ونسمح بأدوار مخصصة للخطط المتقدمة. دور المسؤول لديه تحكم كامل في مساحة العمل، ويمكن للأعضاء إنشاء وتحرير معظم الموارد، ويمكن للمشاهدين القراءة فقط.
حيث تصبح الأمور صعبة هو نطاق الأذونات. يجب أن تكون الأذونات مقتصرة على مساحة العمل افتراضيًا، لكن قد تحتاج إلى أذونات على مستوى المؤسسة (مثل إدارة الفوترة) أو حتى صلاحيات قراءة عبر مساحات العمل لإعداد تقارير موحدة. قم بنمذجة الأذونات كمجموعة من أزواج action:resource، وقم بتعيينها للأدوار. خزّن التعيينات في جدول ربط: (workspace_id, user_id, role_id).
نصيحة احترافية: تجنب التحقق من الصلاحيات على مستوى طبقة التطبيق فقط. قم بدفع أكبر قدر ممكن من منطق الاستحقاق إلى قاعدة البيانات باستخدام أمان مستوى الصف (RLS) أو محرك سياسات مثل OPA. هذا يقلل من فرصة حدوث خطأ في طبقة الويب يعرض بيانات شخص آخر.
أحد الأنماط التي أثبتت فعاليتها هو تخزين دور المستخدم مؤقتًا داخل رمز الجلسة (JWT) بدلاً من الاستعلام عن قاعدة البيانات في كل طلب. لكن كن حذرًا: إذا قمت بتخزين الأدوار في JWTs، يجب أن يكون لديك آلية لإبطال الرموز عند تغيير الدور (مثل انتهاء صلاحية قصير للرمز أو قائمة حظر).
فكر أيضًا في توارث الأدوار: هل يجب أن يكون مدير المؤسسة تلقائيًا مديرًا في جميع مساحات العمل؟ قاعدةنا الأساسية: أدوار المؤسسة توفر سقفًا، لكن أدوار مساحة العمل يمكن أن تكون أكثر تقييدًا. على سبيل المثال، يمكن لمدير المؤسسة الوصول إلى أي مساحة عمل، لكن مدير مساحة العمل لا يمكنه الوصول إلى الفوترة.
الفوترة ونماذج التسعير: بيانات وصفية، وليس منطق أعمال
الفوترة هي حيث يصبح تعدد المستأجرين حقيقيًا. يجب أن ينعكس نموذج التسعير الخاص بك — لكل مقعد، لكل مساحة عمل، على أساس الاستخدام، أو متدرج — في نموذج البيانات الخاص بك، لكن يجب أن يكون نظام الفوترة منفصلاً عن تطبيقك الأساسي. استخدم مزود فوترة تابع لجهة خارجية (Stripe، Recurly، Chargebee) واحتفظ فقط بمعرف الاشتراك ومعرف الخطة في قاعدة البيانات.
نوصي باتباع نهج قاعدة البيانات التالي:
- جدول
plansيحدد معرف الخطة وسعرها وعلامات الميزات (مثلmax_usersوstorage_gbوapi_rate_limit). - جدول
organizationsيحتوي علىcurrent_plan_idوbilling_provider_subscription_id. ربط المؤسسات بمساحات العمل عبر جدول ربط. - جدول
features(أو عمود JSON بسيط) يخزن التجاوزات. على سبيل المثال، إذا تفاوض العميل على سعر مخصص، تجاوز سعر الخطة على مستوى المؤسسة.
الجزء الأصعب هو تقييد الوصول بناءً على الخطة. لديك خياران: فرض الحدود في التطبيق (التحقق من max_users قبل دعوة مستخدم جديد) أو فرضها عبر عدد الصفوف في قاعدة البيانات والمشغلات. نحن نفضل فرض الحدود على مستوى التطبيق لأنه ينتج رسائل خطأ أفضل للمستخدم، لكننا نضيف دائمًا وظيفة تسوية ليلية تضع علامة على المؤسسات التي تتجاوز حدودها.
تتطلب ترقيات الخطط وتخفيضاتها معالجة دقيقة. عندما يرقّي العميل خطته، امنحه الوصول الفوري إلى الميزات الجديدة ولكن قم باحتساب الفاتورة بشكل نسبي عبر مزود الفوترة. عند التخفيض، عليك أن تقرر: هل تمنع الوصول إلى الميزات التي تتجاوز الخطة الجديدة، أم تسمح بفترة سماح؟ نوصي بفترة سماح تمتد لدورة الفوترة الحالية، وبعدها يتم فرض القيود.
درس من الميدان: لا تدع أبدًا فشل الفوترة يؤدي إلى فقدان البيانات. إذا فشلت عملية الدفع، تدهور بأمان (مثل تقييد عمليات الكتابة) ولكن لا تحذف البيانات. سيدفع عميلك في النهاية.
عزل المستأجرين: المشاركة مقابل العزل التام
العزل هو القرار المعماري الأكثر تأثيرًا. المفاضلة التقليدية هي بين قاعدة بيانات مشتركة (قاعدة بيانات واحدة لجميع المستأجرين، مع عمود tenant_id في كل جدول) وقاعدة بيانات لكل مستأجر (يحصل كل مساحة عمل على قاعدة بيانات خاصة بها). لقد جربنا كلا النهجين واستقررنا على نهج هجين لمعظم المشاريع.
- مشتركة مع RLS صارم: مناسبة للمستأجرين الصغار والمتوسطين (أقل من 10 آلاف مستخدم لكل منهم). أمان مستوى الصف مدمج في Postgres، ونستخدم متغير جلسة (
app.tenant_id) لتصفية كل استعلام. هذا هو الأسهل في التشغيل والترقية. - قاعدة بيانات لكل مستأجر: ضرورية عندما يطلب المستأجرون امتثالًا صارمًا (HIPAA، SOC 2، GDPR فيما يتعلق بمكان تخزين البيانات) أو عندما يكون التطبيق كثيف الإدخال/الإخراج لكل مستأجر. العبء التشغيلي حقيقي—يجب تطبيق ترحيلات المخطط على مئات قواعد البيانات—لكن أدوات مثل Flyway وCI الآلي تجعلها قابلة للإدارة.
- مخطط لكل مستأجر: حل وسط باستخدام مخططات منفصلة داخل قاعدة بيانات واحدة. يوفر عزلًا أكثر من جدول مشترك لكن بعبء تشغيلي أقل من قواعد البيانات الكاملة. نستخدم هذا في خططنا الأدنى ونرقّي العملاء إلى قاعدة بيانات لكل مستأجر إذا احتاجوا ذلك.
بغض النظر عن استراتيجية العزل، لا تسمح أبدًا بالوصول المباشر إلى قاعدة البيانات من العميل. وجّه دائمًا عبر طبقة API تفرض هوية المستأجر. ولأجل راحة فريق الاستجابة: لا تستخدم أبدًا tenant_id في عناوين URL دون التحقق من أن المستخدم المصادق ينتمي إلى ذلك المستأجر.
ترحيل البيانات بين مستويات العزل أمر واقع. على سبيل المثال، عندما يتجاوز مستأجر قاعدة البيانات المشتركة، قد تحتاج إلى ترحيله إلى قاعدة بيانات مخصصة. خطط لذلك مبكرًا: اكتب سكريبت ترحيل يصدر ويستورد البيانات، واختبره ببيانات مشابهة للإنتاج. يجب أن يكون من الممكن تشغيله دون توقف باستخدام نهج أزرق-أخضر.
الإعداد الآلي: دع الآلة تقوم بذلك
قد ينجح الإعداد اليدوي للمستأجرين الجدد مع أول عشرة عملاء، لكنه لا يتوسع. كما يسلط براءة اختراع ContractorHUB الأخيرة الضوء، فإن التنفيذ بدون تدخل بشري هو عامل تمييز رئيسي لتطبيقات SaaS متعددة المستأجرين [1]. لقد بنينا سير عمل إعداد يقوم بأتمتة كل شيء بدءًا من إنشاء قاعدة البيانات (أو استنساخ المخطط) إلى تغذية البيانات الافتراضية وإرسال رسائل الترحيب الإلكترونية.
خط أنابيب إعداد آلي نموذجي:
- يسجل المستخدم، وينشئ مؤسسة، ويختار خطة.
- يؤدي webhook من مزود الفوترة إلى تشغيل مهمة إعداد (مثل دالة serverless أو وظيفة Kubernetes).
- تنشئ المهمة طبقة العزل للمستأجر (مخطط أو قاعدة بيانات)، وتجري الترحيلات الأولية، وتملأ الأدوار والإعدادات الافتراضية.
- ترسل مهمة ثانية بريدًا إلكترونيًا يحتوي على تعليمات تسجيل الدخول والخطوات التالية.
- يتم إعادة توجيه المستخدم إلى مساحة العمل الجديدة - كاملة الوظائف - في غضون ثوانٍ.
التكرارية (Idempotency) غير قابلة للتفاوض هنا. إذا فشلت مهمة الإعداد في منتصف الطريق، يجب أن يكون من الآمن إعادة المحاولة. نغلف العملية بأكملها في آلة حالة مع عمود provisioning_status في صف المؤسسة: pending → creating → active → failed. يتم إرسال الحالات الفاشلة إلى قائمة انتظار ميتة للتدخل البشري.
لا تنسَ توفير البنية التحتية الداعمة: سجلات DNS للنطاقات المخصصة، أدوات تسخين ذاكرة التخزين المؤقت لشبكة CDN، حدود معدل واجهة برمجة التطبيقات لكل مستأجر، وتنبيهات المراقبة. قم بأتمتة كل ما يمكن برمجته، لأن الخطوات اليدوية ستُنسى تحت الضغط.
الخلاصة: عقلية تعدد المستأجرين
تعدد المستأجرين ليس شيئًا يمكن إضافته بعد الإطلاق. بل يجب أن يوجه نموذج بياناتك، والتحكم في الوصول، وتكامل الفوترة، واستراتيجية النشر منذ اليوم الأول. الخبر السار: إذا أتقنت هذه الركائز الأربع—مساحات العمل، الأدوار، الفوترة، العزل—سيصبح بناء وصيانة بقية تطبيق SaaS أسهل بشكل ملحوظ.
كل تطبيق SaaS مختلف، لكن الأنماط المذكورة أعلاه خدمتنا جيدًا عبر الصناعات. سواء كنت تبدأ مشروعك الأولي أو تتوسع لآلاف المستأجرين، نشجعك على التفكير بعمق في هذه القرارات. وإذا كنت ترغب في مراجعة معماريّتك، يسعدنا دائمًا مراجعتها.


