Blog'a dön
•
ByteGurus

Ölçeklenebilir SaaS İçin Çok Kiracılı Mimari Kalıpları

SaaS uygulamalarında çok kiracılı mimari: kiracı başına veritabanı, şema ve satır düzeyinde izolasyon, PostgreSQL RLS ve doğru kalıbı seçme ölçütleri.

Çok Kiracılı SaaS Mimari

Çok kiracılı (multi-tenant) mimari, bir uygulamanın tek kurulumla birden fazla müşteriye hizmet vermesidir. Fintech platformu, kurumsal yönetim sistemi ya da ekip uygulaması kuruyor olun, kiracıları nasıl ayırdığınız maliyeti, güvenliği ve büyümeyi birlikte belirler. Bu yazı üç temel kalıbı, aralarındaki ödünleşimleri ve doğru seçimi nasıl yapacağınızı anlatıyor.

Çok kiracılık nedir

Çok kiracılı bir sistemde tek bir uygulama birçok müşteriye (kiracıya) hizmet verir ve her kiracının verisi diğerlerinden ayrı tutulur. Her müşteriye ayrı altyapı kurulan tek kiracılı modelden farkı, kaynakların paylaşılması ama verinin mantıksal olarak ayrılmasıdır.

Kazancı açık: daha az işletme yükü, müşteri başına daha düşük altyapı maliyeti, tek dağıtım hattı ve yeni özelliğin herkese aynı anda ulaşması. Bedeli de açık: veri izolasyonu, güvenlik ve kiracıya özel ayarlar daha dikkatli tasarım ister.

Üç temel kalıp

1. Kiracı başına veritabanı

Her kiracıya ayrı bir veritabanı verilir. İzolasyonu sağlamanın en anlaşılır yoludur ve uyum gereksinimlerinin sıkı olduğu sektörlerde (finans, sağlık) sık tercih edilir.

Artıları:

  • En yüksek veri izolasyonu
  • Kiracıya özel yedekleme ve geri yükleme
  • Kiracı bazında denetim kolaylığı
  • Bir kiracının verisini taşımak ya da silmek basit

Eksileri:

  • Çok sayıda veritabanını işletmek zahmetli
  • Altyapı maliyeti yüksek
  • Kiracılar arası raporlama zor
  • Şema değişikliklerini yüzlerce veritabanına uygulamak ayrı bir iş

2. Ortak veritabanı, kiracı başına şema

Tek bir veritabanı sunucusu, her kiracı için ayrı şema. İstek, kiracı kimliğine göre doğru şemaya yönlendirilir:

CREATE SCHEMA tenant_acme;
CREATE SCHEMA tenant_globex;

CREATE TABLE tenant_acme.users (
  id    uuid PRIMARY KEY,
  email text NOT NULL
);

-- İstek başında doğru şemayı seçmek
SET search_path TO tenant_acme;

Artıları:

  • Kiracı başına veritabanından daha verimli kaynak kullanımı
  • İşletmesi daha kolay
  • İzolasyon ile maliyet arasında iyi bir denge

Eksileri:

  • Sorgu yönlendirmesinde hata payı
  • Kiracı sayısı arttıkça migration’lar uzar
  • Gürültülü komşu (noisy neighbor) etkisi
  • Bağlantı havuzu ile search_path’in birlikte yönetilmesi dikkat ister

3. Ortak tablolar, satır düzeyinde izolasyon

En maliyet etkin kalıp: tüm kiracıların verisi aynı tablolarda, her satırda bir tenant_id sütunuyla. Erişim uygulama mantığıyla ve tercihen veritabanı politikalarıyla denetlenir.

CREATE TABLE projects (
  id         uuid PRIMARY KEY,
  tenant_id  uuid NOT NULL,
  owner_id   uuid NOT NULL,
  name       text NOT NULL,
  created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX projects_tenant_idx ON projects (tenant_id);

Artıları:

  • En düşük altyapı maliyeti
  • En kolay işletme
  • Kiracılar arası analitik basit
  • Çok sayıda küçük kiracıya en uygun kalıp

Eksileri:

  • İzolasyon tamamen doğru filtrelemeye bağlı
  • Unutulan tek bir WHERE tenant_id = ... veri sızıntısı demek
  • Tek bir kiracıyı yedeklemek ya da geri yüklemek zor

Bu riski azaltmanın en etkili yolu filtreyi uygulamaya bırakmamak, PostgreSQL’in satır düzeyi güvenliğiyle (RLS) veritabanına da yazmaktır:

ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
ALTER TABLE projects FORCE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON projects
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

Uygulama her işlemin başında kiracıyı oturuma yazar; filtreyi unutan bir sorgu bile başka kiracının satırını göremez:

// Kiracı bağlamı her transaction'ın başında set edilir
async function withTenant(pool, tenantId, work) {
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    await client.query("SELECT set_config('app.tenant_id', $1, true)", [tenantId]);
    const result = await work(client);
    await client.query('COMMIT');
    return result;
  } catch (err) {
    await client.query('ROLLBACK');
    throw err;
  } finally {
    client.release();
  }
}

set_config(..., true) ayarı yalnız o transaction için geçerli kılar; bağlantı havuza döndüğünde bir sonraki istek önceki kiracının bağlamını devralmaz.

Kiracıyı tanımak

Hangi kalıbı seçerseniz seçin, her isteğin hangi kiracıya ait olduğunu güvenilir biçimde bilmeniz gerekir:

  • Alt alan adı: acme.uygulama.com
  • Yol: uygulama.com/acme
  • Kimlik belirteci (JWT) içeriği: kiracı kimliği token’da, imzayla korunur
  • Başlık: X-Tenant-ID gibi; tek başına güvenilmez, istemci istediğini yazabilir

Kiracı kimliği istemcinin gönderdiği bir değerden değil, doğrulanmış kimlikten türetilmelidir. Alt alan adı ile token’daki kiracı birbirini tutmuyorsa istek reddedilir.

Uygulamada dikkat edilecekler

Güvenlik ve izolasyon

  • Kiracı bağlamını her veri erişim noktasında doğrulayın
  • Ortak tablolarda PostgreSQL RLS kullanın
  • Kiracı verisine erişimi denetim kaydına yazın
  • İzolasyonu test edin: A kiracısının oturumuyla B’nin kaydını isteyen otomatik testler
  • Önbellek anahtarlarına kiracıyı ekleyin (tenant:{id}:...); aksi hâlde önbellek sızıntı kaynağı olur

Ölçekleme

  • Parçalama (sharding): kiracıları birden fazla veritabanına dağıtmak
  • Okuma kopyaları: raporlamayı işlem yükünden ayırmak
  • Büyük kiracıyı ayırmak: satır düzeyinde başlayıp büyüyen kiracıyı kendi veritabanına taşıyabilmek

İşletme

  • Kiracı açma ve kapatma (veri silme dahil) otomatik olmalı
  • İzleme metrikleri kiracı bazında ayrılabilmeli
  • Bir kiracıdaki sorun ya da geri alma diğerlerini etkilememeli

Doğru kalıbı seçmek

Kiracı başına veritabanı:

  • Sıkı düzenlenen sektörler, müşterinin verisinin fiziksel olarak ayrı durmasını sözleşmeyle istediği durumlar
  • Kiracılar arasında veri hacmi çok farklıysa

Kiracı başına şema:

  • Onlarca ya da birkaç yüz kiracı
  • İzolasyon ile işletme kolaylığı arasında denge arıyorsanız

Satır düzeyinde izolasyon:

  • Binlerce kiracı
  • Maliyet öncelikliyse ve kiracılar birbirine benziyorsa
  • RLS ve izolasyon testleriyle desteklenmek şartıyla

Pek çok ürün satır düzeyinde başlar ve büyük ya da düzenlenmiş kiracıları sonradan kendi veritabanına taşır. Bunu mümkün kılan, kiracı kimliğinin baştan her tabloda ve her olayda bulunmasıdır.

Çok kiracılı mimari tek kalıplık bir karar değil; iş modelinize, müşterilerinize, mevzuata ve ekibinize göre şekillenir. Bu kararı birlikte değerlendirmek isterseniz bize yazın.

B

ByteGurus

Yazar

Tüm yazılara dön
Başlamaya hazır mısınız?

Projenize başlamaya hazır mısınız?

Fikirlerinizi hayata geçirmek için size nasıl yardımcı olabileceğimizi konuşalım.