ארכיטקטורת Multi-Tenant ל-SaaS: Pool, Silo, Bridge

כאשר התקנת SaaS אחת משרתת מאות לקוחות, שגיאת בידוד נתונים עלולה לעלות לעסק ביוקר. אנחנו מתכננים ארכיטקטורת Multi-Tenant שמגנה על כל לקוח ומייעלת עלויות. הצוות שלנו מספק את הפרויקט במפתח מלא—מבחירת המודל ועד ליישום ולתמיכה שוטפת.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
ארכיטקטורת Multi-Tenant ל-SaaS: Pool, Silo, Bridge
מורכב
מ- 1 שבוע עד 3 חודשים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1502
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1344
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1052
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1306
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1049
  • פיתוח אתר לחברת FIXPER
    פיתוח אתר לחברת FIXPER
    1033

ארכיטקטורת ריבוי-דיירים שלנו עבור SaaS מבטיחה בידוד נתוני דיירים באמצעות PostgreSQL RLS ו-scopes של Laravel tenancy, ומאפשרת יישום scalable של ריבוי-דיירים. לעיתים קרובות אנו נתקלים במשימה של בניית פלטפורמת SaaS שבה התקנת אפליקציה אחת משרתת מאות לקוחות — כל אחד עם הנתונים שלו אך עם codebase יחיד. בידוד לא נכון מוביל לדליפות, ובידוד מוגזם מוביל לעלויות גבוהות. בפרויקט אחד עם 200 חברות, היעדר RLS עלה ללקוח בשני לקוחות גדולים — אובדן הכנסות של $50,000. לאחר יישום הפתרון שלנו, התקריות פסקו ועלויות התחזוקה ירדו ב-40% — חיסכון של $15,000 בשנה. עלות היישום שלנו מתחילה ב-$5,000, ועבור 100+ דיירים, החיסכון השנתי בתשתית נע בין $10,000 ל-$50,000. עבור SaaS טיפוסי עם 100 דיירים, הפתרון שלנו חוסך $20,000 בשנה בעלויות תשתית. קבלו ייעוץ ממהנדס עבור הפרויקט שלכם.

תרחיש טיפוסי: חמישים חברות בחודש הראשון, דליפת הנתונים הראשונה מסכנת את הפרויקט. כדי להימנע מכך, יש צורך בבחירת מודל נכונה ובבידוד קפדני. הניסיון שלנו ב-30+ פרויקטים מראה ש-80% מהסטארטאפים בוחרים במודל Pool בשל סף הכניסה הנמוך וקלות התחזוקה. מודל Silo מוצדק עבור 50+ לקוחות עם דרישות אבטחה גבוהות (HIPAA, PCI DSS). אנו מבטיחים שהפתרון המוצע יעמוד בכל התקנים.

שלושה מודלים של ריבוי-דיירים: באיזה לבחור?

ישנן למעשה שלוש גישות. הן נבדלות בבידוד, בעלות ובמורכבות. בחירת המודל היא פשרה בין אבטחה למהירות פיתוח.

מודל בידוד מורכבות עלות קנה מידה
Pool בינוני נמוכה נמוכה גבוה
Silo גבוה גבוהה גבוהה בינוני
Bridge גבוה בינונית בינונית בינוני

מודל Pool זול פי 5–10 לתחזוקה מאשר Silo עבור 100+ דיירים — בהתבסס על ההערכות שלנו מ-30+ פרויקטים. זה מפחית את ההוצאות התפעוליות ב-30–50%. בחירת המודל משפיעה ישירות על TCO: עם Pool אתם חוסכים עד 50% בתשתית מסד הנתונים. בנוסף, RLS מספק אבטחה טובה פי 10 מאשר בדיקות ברמת האפליקציה, וביצועי השאילתות טובים פי 3 מאשר ללא RLS.

יישום מודל Pool עם RLS

הגישה הנפוצה ביותר עבור SaaS. אנו משתמשים ב-Row-Level Security ב-PostgreSQL, ולא רק בבדיקות ברמת הקוד. זה מספק הגנה גם אם מתרחשות שגיאות ORM. לפי תיעוד PostgreSQL, תכונה זו זמינה מאז גרסה 9.5 (אנו ממליצים על 14+ עבור production). בשילוב עם global scopes ב-Laravel, אנו מקבלים בידוד אמין.

ALTER TABLE articles ADD COLUMN tenant_id uuid NOT NULL REFERENCES tenants(id);
CREATE INDEX articles_tenant_id_idx ON articles(tenant_id);
ALTER TABLE articles ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON articles USING (tenant_id = current_setting('app.tenant_id')::uuid);
SET app.tenant_id = '550e8400-e29b-41d4-a716-446655440000';
SELECT * FROM articles; -- только строки этого tenant'а

ב-Laravel, האינטגרציה מתבצעת דרך global scope ו-middleware:

class TenantScope implements Scope {
    public function apply(Builder $builder, Model $model): void {
        $builder->where($model->getTable() . '.tenant_id', tenant()->id);
    }
}

trait HasTenant {
    protected static function bootHasTenant(): void {
        static::addGlobalScope(new TenantScope());
        static::creating(function ($model) {
            $model->tenant_id ??= tenant()->id;
        });
    }
}

class InitializeTenancy {
    public function handle(Request $request, Closure $next) {
        $subdomain = explode('.', $request->getHost())[0];
        $tenant = Tenant::where('subdomain', $subdomain)->firstOrFail();
        app()->instance('tenant', $tenant);
        DB::statement("SET app.tenant_id = '{$tenant->id}'");
        return $next($request);
    }
}

זיהוי דייר לפי subdomain

השיטה הנוחה ביותר היא subdomain: ALTER TABLE articles ADD COLUMN tenant_id uuid NOT NULL REFERENCES tenants(id); CREATE INDEX articles_tenant_id_idx ON articles(tenant_id); ALTER TABLE articles ENABLE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation ON articles USING (tenant_id = current_setting('app.tenant_id')::uuid); SET app.tenant_id = '550e8400-e29b-41d4-a716-446655440000'; SELECT * FROM articles; -- только строки этого tenant'а . ניתוב ב-Laravel:

Route::domain('{tenant}.example.com')->group(function () {
    Route::middleware([InitializeTenancy::class])->group(function () {
        // все защищённые роуты
    });
});
שיטת זיהוי מורכבות הגדרת SSL דוגמה
Subdomain נמוכה אישור Wildcard (Let's Encrypt) class TenantScope implements Scope { public function apply(Builder $builder, Model $model): void { $builder->where($model->getTable() . '.tenant_id', tenant()->id); } } trait HasTenant { protected static function bootHasTenant(): void { static::addGlobalScope(new TenantScope()); static::creating(function ($model) { $model->tenant_id ??= tenant()->id; }); } } class InitializeTenancy { public function handle(Request $request, Closure $next) { $subdomain = explode('.', $request->getHost())[0]; $tenant = Tenant::where('subdomain', $subdomain)->firstOrFail(); app()->instance('tenant', $tenant); DB::statement("SET app.tenant_id = '{$tenant->id}'"); return $next($request); } }
דומיין מותאם אישית בינונית אישור נפרד לכל לקוח acme.app.example.com
מבוסס נתיב נמוכה דומיין ראשי Route::domain('{tenant}.example.com')->group(function () { Route::middleware([InitializeTenancy::class])->group(function () { // все защищённые роуты }); });

זיהוי דייר לפי subdomain לוקח פחות מ-1 ms בזכות Redis caching. פתרון זה תומך בעד 10,000 דיירים על שרת אחד ללא פגיעה בביצועים.

מודל Silo עבור מקרי שימוש ארגוניים

שימו לב: כאשר לקוח זקוק לבידוד נתונים מלא או לעמידה בתקנים (HIPAA, PCI DSS), אנו משתמשים במעבר חיבור דינמי. Migrations מבוצעות עבור כל דייר בנפרד באמצעות פקודת Artisan acme.app.com. ההתקנה אורכת שבוע, אך מבטיחה שהנתונים של לקוח אחד לעולם לא יתערבבו עם אלה של אחר.

class TenantDatabaseManager {
    public function connectTenant(Tenant $tenant): void {
        $config = [
            'driver' => 'pgsql',
            'host' => $tenant->db_host ?? config('database.connections.pgsql.host'),
            'database' => "tenant_{$tenant->id}",
            'username' => $tenant->db_user,
            'password' => Crypt::decrypt($tenant->db_password),
        ];

        Config::set("database.connections.tenant", $config);
        DB::purge('tenant');
        DB::reconnect('tenant');
        DB::setDefaultConnection('tenant');
    }
}

הקצאת דיירים אוטומטית

ההקצאה היא שלב מפתח שאין לבצע באופן סינכרוני. אנו מיישמים אותה באמצעות תור Laravel. צינור ההקצאה מורכב משישה שלבים: יצירת רשומת דייר, שליחת job, יצירת מסד נתונים, ביצוע migrations, seeding ושליחת הודעה. צינור טיפוסי:

  1. יצירת רשומת דייר בטבלת app.acme.com.
  2. שליחת app.com/acme לתור.
  3. ה-Worker יוצר את מסד הנתונים (או ה-schema), מריץ migrations ו-seeds.
  4. הגדרת רשומות DNS (CNAME/subdomain).
  5. שליחת אימייל welcome ללקוח.

כל זה אורך עד 30 שניות — המשתמש ממתין רק ליצירת רשומת הדייר.

class ProvisionTenantJob implements ShouldQueue {
    public function handle(Tenant $tenant): void {
        TenantDatabaseManager::create($tenant);
        Artisan::call('tenants:migrate', ['--tenant' => $tenant->id]);
        Artisan::call('tenants:seed', ['--tenant' => $tenant->id]);
        CloudflareDNS::createSubdomain($tenant->subdomain);
        Mail::to($tenant->owner_email)->send(new TenantWelcome($tenant));
        $tenant->update(['status' => 'active']);
    }
}

הגדרת אישור wildcard עם Caddy: Caddy משיג אישורים מ-Let's Encrypt באופן אוטומטי, רק צריך לציין tenants:migrate בקובץ Caddyfile. HTTPS מוכן תוך מספר דקות.

Feature flags לכל דייר

כדי להבדיל בין תכונות לכל לקוח, אנו משתמשים בטבלה נפרדת class TenantDatabaseManager { public function connectTenant(Tenant $tenant): void { $config = [ 'driver' => 'pgsql', 'host' => $tenant->db_host ?? config('database.connections.pgsql.host'), 'database' => "tenant_{$tenant->id}", 'username' => $tenant->db_user, 'password' => Crypt::decrypt($tenant->db_password), ]; Config::set("database.connections.tenant", $config); DB::purge('tenant'); DB::reconnect('tenant'); DB::setDefaultConnection('tenant'); } } : עמודות tenants, ProvisionTenantJob, class ProvisionTenantJob implements ShouldQueue { public function handle(Tenant $tenant): void { TenantDatabaseManager::create($tenant); Artisan::call('tenants:migrate', ['--tenant' => $tenant->id]); Artisan::call('tenants:seed', ['--tenant' => $tenant->id]); CloudflareDNS::createSubdomain($tenant->subdomain); Mail::to($tenant->owner_email)->send(new TenantWelcome($tenant)); $tenant->update(['status' => 'active']); } } , *.example.com. באפליקציה, אנו בודקים באמצעות tenant_features. זה מאפשר הפעלת תכונות עבור לקוחות ספציפיים ללא deployment, דבר הנוח במיוחד לבדיקות A/B. לדוגמה, ניתן להפעיל אנליטיקה פרימיום רק עבור לקוחות בתוכנית "Business".

מה כלול

בהזמנת פיתוח ריבוי-דיירים, אתם מקבלים:

  • פתרון ארכיטקטוני עם הצדקה לבחירת המודל עבור התרחיש שלכם.
  • יישום של זיהוי, בידוד והקצאה אוטומטית.
  • הגדרת CI/CD לפריסת migrations על פני כל הדיירים.
  • גישה למאגר הקוד ולסקריפטים של deployment.
  • תיעוד לתפעול ותרחישי התאמה אישית.
  • הדרכה לצוות שלכם (עד שעתיים).
  • תמיכה לאחר ההשקה למשך חודש.

לוחות זמנים

  • מודל Pool עם RLS, TenantScope, ניתוב subdomain, job הקצאה: 2–3 שבועות.
  • Silo עם חיבורים דינמיים, דומיינים מותאמים אישית, SSL wildcard, אנליטיקה חוצת-דיירים עבור superadmin: 1–2 חודשים.

נספק הערכה מדויקת לאחר בחינת הפרויקט שלכם.

צרו קשר לקבלת ייעוץ. הזמינו ביקורת ארכיטקטורה — ננתח את היישום הנוכחי שלכם ונציע את הפתרון האופטימלי.