Laravel ile Multi-Tenancy (Çok Kiracılı Mimari) Yapısı ve SaaS Uygulamaları

L

Tek bir Laravel uygulamasının, birden fazla müşteriyi (tenant) aynı anda izole şekilde yönetmesini ister misiniz?
Modern SaaS (Software as a Service) projelerinin kalbinde yer alan multi-tenancy (çok kiracılı mimari) tam olarak bunu sağlar.

Bu yazıda:

  • Multi-tenancy mimarisinin mantığı

  • Laravel’de hangi senaryolarda nasıl kurulur

  • Sıfırdan kendi yapınızı geliştirmek

  • Veya hazır bir çözüm: stancl/tenancy paketi kullanmak

  • Performans ve güvenlik ipuçları

hepsini adım adım, bol örnekle ve uygulamalı kod parçalarıyla bulacaksınız.

Multi-Tenancy Nedir?

Multi-Tenancy, bir uygulamanın altyapısının birden çok müşteri (tenant) tarafından paylaşılmasıdır.
Her tenant:
✅ Aynı kod tabanını kullanır
✅ Verileri diğer tenant’lardan tamamen ayrıdır
✅ Kendi özel yapılandırmasına sahip olabilir

Örneğin: Shopify, Slack, Notion… Bunlar hepsi SaaS’ta çok kiracılı yapı kullanır.

Multi-Tenancy Mimarisi: Hangi Tipleri Var?

Laravel ile SaaS geliştirmek isteyenlerin önce hangi yapıyı seçeceğine karar vermesi gerekir.

1) Shared Database - Shared Schema

  • Tüm tenant’lar aynı veritabanını ve tabloları paylaşır

  • Tablo satırlarında tenant_id alanı bulunur

  • Basit yönetim, düşük maliyet

  • Büyük ölçeklerde query optimizasyonu kritik

2) Separate Database

  • Her tenant’ın kendi veritabanı vardır

  • Veriler birbirinden tamamen ayrıdır

  • Güvenlik ve veri gizliliği üst düzeydedir

  • Daha karmaşık bir bağlantı yönetimi gerekir

3) Separate Schema (Alternatif)

  • Aynı veritabanı içinde her tenant için farklı şema (PostgreSQL’de yaygın)

  • Orta ölçekli SaaS projelerinde ideal olabilir

Laravel’de Sıfırdan Multi-Tenancy Nasıl Kurulur?

Burada Shared Database yapısını temel alarak ilerleyeceğiz.
En temel haliyle: tenants tablosu + tenant_id scoping.

Adım 1: Tenant Modeli ve Migration

Önce tenant’ları saklayacak temel bir tablo oluşturalım.

php artisan make:model Tenant -m
// database/migrations/xxxx_xx_xx_create_tenants_table.php
Schema::create('tenants', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('domain')->unique();
    $table->timestamps();
});

Adım 2: Tenant Tespiti için Middleware

Her istek geldiğinde hangi tenant’a ait olduğunu bulmak için bir middleware kullanılır.
Burada örnek olarak domain bazlı tespit yapıyoruz.

php artisan make:middleware IdentifyTenant
// app/Http/Middleware/IdentifyTenant.php

namespace App\Http\Middleware;

use App\Models\Tenant;
use Closure;
use Illuminate\Support\Facades\App;

class IdentifyTenant
{
    public function handle($request, Closure $next)
    {
        $host = $request->getHost();

        $tenant = Tenant::where('domain', $host)->first();

        if (!$tenant) {
            abort(404, 'Tenant not found.');
        }

        App::instance('currentTenant', $tenant);

        return $next($request);
    }
}

Kernel’e ekle:

protected $middleware = [
    \App\Http\Middleware\IdentifyTenant::class,
];

Adım 3: Tenant Bazlı Veri İzolasyonu

Örneğin posts tablosu tenant bazlı olsun.
Her Post kaydı mutlaka tenant_id ile işaretlenmeli.

// app/Models/Post.php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected static function booted()
    {
        static::addGlobalScope('tenant_id', function (Builder $builder) {
            $tenant = app('currentTenant');
            $builder->where('tenant_id', $tenant->id);
        });

        static::creating(function ($model) {
            $model->tenant_id = app('currentTenant')->id;
        });
    }
}

Bu sayede:

Post::all(); // Sadece o tenant’a ait kayıtlar gelir

Adım 4: Ayrı Veritabanı Kullanmak İsterseniz

Separate Database senaryosunda middleware içinde dinamik bağlantı değiştirmek gerekir.

// IdentifyTenant Middleware içinde

config([
    'database.connections.tenant' => [
        'driver' => 'mysql',
        'host' => '127.0.0.1',
        'database' => 'tenant_' . $tenant->id,
        'username' => 'root',
        'password' => '',
    ],
]);

DB::setDefaultConnection('tenant');

Model’de protected $connection = 'tenant'; şeklinde ayarlayarak ilgili veritabanına geçebilirsiniz.

Alternatif Yol: Tenancy for Laravel Paketi

Laravel topluluğunda stancl/tenancy en popüler çözümdür.
Özellikleri:
✅ Domain veya subdomain bazlı tenant yönetimi
✅ Separate database desteği
✅ Tenant başına migration & seed desteği
✅ Cache, queue, storage izolasyonu

Kurulum:

composer require stancl/tenancy
php artisan tenancy:install
php artisan migrate

Tenant başlatmak:

tenancy()->initialize($tenant);

Tenant migration:

php artisan tenancy:migrate

Ve alt alan adı bazlı örnek:

Route::domain('{account}.yoursaas.com')->group(function () {
    Route::get('/', function ($account) {
        tenancy()->initialize($account);
        return view('dashboard');
    });
});

Güvenlik & Performans İpuçları

✅ Her tenant için storage, cache, queue gibi bileşenleri izole et.
✅ Büyük veri hacminde read replica, partitioning gibi çözümler kullan.
✅ Verileri tenant_id bazlı scoping ile her sorguda filtrele.
✅ API token veya session yönetiminde tenant doğrulamasını unutma.
✅ Subdomain veya domain bazlı yapı SEO açısından da önemlidir.

Kimler İçin İdeal?

  • Birden fazla müşteri için tek bir Laravel uygulaması çalıştırmak isteyen girişimler.

  • SaaS iş modeli kurmak isteyen startup’lar.

  • Düşük bakım maliyetiyle ölçeklenebilir sistem tasarlamak isteyen ekipler.

Sonuç

✔ Multi-tenancy, SaaS dünyasında olmazsa olmazdır.
✔ Laravel, hem paket desteği hem framework esnekliği ile çok güçlüdür.
✔ İster sıfırdan kur, ister Tenancy for Laravel gibi bir paket kullan, önemli olan: veri izolasyonu ve güvenliği doğru planlamak.

By Aydın Yağız

Aydın Yağız

Teknolojiye olan tutkumla inovasyonu destekler, kullanıcı deneyimini önceliklerim arasına alırım. Kendi yeteneklerimi ve bilgilerimi paylaşarak, daha geniş bir topluluğun faydalanmasını sağlarım. İş birliği içinde hareket ederek, geleceğin teknoloji dünyasına katkıda bulunmayı hedeflerim. Sizi de bu heyecan verici yolculuğa davet ediyor, fikirlerinizi paylaşmaya ve teknolojiye dair sınırları zorlamaya teşvik ediyorum. Birlikte büyüyelim ve yeni ufuklara açılalım!

İletişime Geçin

Kodlama dünyasına adım atın ve deneyimlerinizi paylaşın. Siz de bu aktif topluluğa katılarak yeni bağlantılar kurun, fikir alışverişinde bulunun ve bilgi birikiminizi artırın.

Özelleştir

Farklı yazı tipleri ve renk seçenekleriyle stilinizi kişiselleştirin. Aşağıdaki örneklerden birini deneyerek sizin için en uygun olanı seçin.

Yazı Tipi Örnekleri

Renk Örnekleri