Multi-tenant SaaS'te veritabanı izolasyonu: ayrı DB mi, şema mı, tenant_id mi?
Soru
Yeni bir SaaS geliştiriyorum; müşteri (tenant) verilerini izole etmem gerek. Üç seçenek var: her müşteriye ayrı DB (database-per-tenant), aynı DB'de ayrı şemalar (schema-per-tenant), ya da tek DB'de `tenant_id` kolonu (shared). Güvenlik, yedekleme kolaylığı, maliyet ve şema migration'ı düşünerek 10.000 aktif müşteriye ölçeklenecek en optimum mimariyi nasıl seçerim?
Cevap
Kısa cevap: 10.000 tenant ölçeğinde pragmatik cevap, her yerde tenant_id olan shared bir DB + izolasyonu Postgres Row-Level Security’ye gömmek.
Önce neden diğer ikisini elediğimi söyleyeyim, çünkü karar bu sayıda operasyona bakar:
- Database-per-tenant 10k’da ölçeklenmez. Her tenant için ayrı DB demek 10.000 migration, 10.000 connection pool, 10.000 backup işi demek. İzolasyonu mükemmel verir ama operasyonel yükü altında ezilirsin. Bu, ancak az sayıda büyük müşteride mantıklı.
- Schema-per-tenant orta yol ama o da zorlanır. Tek DB’de ayrı şema, izolasyon ile yönetim arasında bir köprü; fakat 10k şemada katalog (catalog) şişer, migration hâlâ N kere koşar. Birkaç yüz tenant’a kadar iyi, on bine değil.
- Shared DB + her yerde
tenant_id. Tek şema, her tablodatenant_id. Backup ve migration en basit burada — tek DB, tek migration. Takas ettiğin şey güvenlik; onu da RLS ile geri satın alırsın. - İzolasyonu RLS ile DB’ye göm. Postgres Row-Level Security ile her sorgu otomatik
tenant_id’ye scope’lansın. İzolasyon, “geliştirici umarım her query’de scope koymuştur” varsayımında değil, veritabanının kendisinde yaşasın. Bu, sızıntıya karşı asıl savunma. - ORM scope’u + indeks/partition ekle. ORM katmanında bir tenant scope koy (defense-in-depth), sıcak tabloları
tenant_idile indeksle/partition’la. Ve bir “whale” tenant büyürse onu kendi DB’sine promote etme yolunu baştan açık tut.
Sonuç: Ben olsam shared DB + her yerde tenant_id + Postgres RLS kurardım. Backup ve migration shared modelde en basit; güvenlik ödediğin bedel ama onu RLS ile geri alıyorsun. ORM scope’unu ikinci savunma katmanı yap, sıcak tabloları tenant_id ile partition’la, dev büyüyen tenant için kendi DB’sine taşıma kapısını açık bırak. Veri mimarisinin neden böyle kurulduğunu sade.dev’de açıyorum.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.