Makalelere Dön

Next.js ve .NET ile B2B SaaS Multi-Tenant (Çok Kiracılı) Mimari

Haziran 2026
8 dk okuma

Modern bir B2B SaaS platformu inşa ederken, en kritik mühendislik kararlarından biri "Multi-Tenant" (Çok Kiracılı) mimarinin nasıl kurulacağıdır. Tenant izolasyonu sadece bir güvenlik gereksinimi değil, aynı zamanda ölçeklenebilirlik için bir zorunluluktur.

Multi-Tenant Yaklaşımları: Hangisini Seçmeli?

Bir SaaS uygulamasında veriyi ayırmanın (Data Isolation) 3 temel yolu vardır:

  • Shared Database, Shared Schema (En Ucuz & En Riskli): Tüm müşteriler aynı tabloda yer alır, sadece TenantId kolonu ile filtrelenir.
  • Shared Database, Separate Schemas (Dengeli): Tek veritabanı ancak her müşteri (tenant) için ayrı bir veritabanı şeması (schema) bulunur. (Ör: PostgreSQL schemas)
  • Separate Databases (En Güvenli & En Pahalı): Her müşteri için fiziksel olarak ayrı bir veritabanı sunucusu/instance'ı ayağa kaldırılır. Kurumsal anlaşmalarda tercih edilir.

Next.js Edge Middleware ile Subdomain Routing

Kullanıcı deneyimini kusursuzlaştırmak için her tenant'a kendine özel bir subdomain vermeliyiz (Örn: acme.saas.com). Next.js'in Edge Middleware'i tam olarak bu iş için biçilmiş kaftandır.

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(req: NextRequest) {
  const url = req.nextUrl;
  const hostname = req.headers.get('host') || '';

  // Root domain kontrolü (Örn: localhost:3000 veya saas.com)
  const isRootDomain = hostname === process.env.NEXT_PUBLIC_ROOT_DOMAIN;

  if (!isRootDomain) {
    // Subdomain'i alıyoruz (Örn: 'acme' from 'acme.saas.com')
    const tenantSlug = hostname.split('.')[0];
    
    // İsteği tenant'a özel path'e rewrite ediyoruz
    url.pathname = `/${tenantSlug}${url.pathname}`;
    return NextResponse.rewrite(url);
  }
}

.NET Core ve Entity Framework ile Tenant İzolasyonu

Backend tarafında (bizim örneğimizde .NET 8 Web API) gelen isteklerdeki JWT token üzerinden veya header'dan TenantId bilgisini okuyup Entity Framework Global Query Filters kullanarak geliştirici hatasını sıfıra indirebiliriz.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    
    // Tüm sorgularda otomatik Tenant filtresi uygular
    // Geliştirici "Where(x => x.TenantId == ...)" yazmayı unutsa bile veriler karışmaz!
    modelBuilder.Entity<Order>().HasQueryFilter(x => x.TenantId == _currentTenantService.TenantId);
}

Sonuç ve Performans Etkisi

Next.js ve .NET ikilisi, modern bir SaaS mimarisi için muazzam bir esneklik sunar. Vercel'in Edge ağı (CDN) üzerinden tenant tespiti yapmak "0" ms (sıfır gecikme) ile gerçekleşir. Böylece kullanıcı tenant.saas.com adresine girdiğinde hiçbir yönlendirme (redirect) hissetmeden doğrudan kendi izole ortamına düşer.