ADR-005: Multi-Tenant Izolasyon Stratejisi
| Durum | Kabul Edildi |
| Tarih | 2025-11 |
| Karar Veren | Güçlü Ceyhan |
Baglam
Zeus 2.0, birden fazla organizasyonun (GES isletmecisi, enerji sirketi, bakim firması) ayni altyapiyi paylasmasi gereken bir SaaS platformudur. Her tenant'in verileri, cihazlari ve kullanicilari diger tenant'lardan izole olmalidir.
Izolasyon gereksinimleri:
- Veri izolasyonu: Tenant A'nin olcum verileri Tenant B tarafindan gorulemez
- API izolasyonu: Her API istegi yalnizca ilgili tenant'in verilerini dondurur
- MQTT izolasyonu: Cihazlar yalnizca kendi tenant'inin topic'lerine erisebilir
- Performans izolasyonu: Bir tenant'in yuku diger tenant'lari etkilememelidir (en azindan minimize edilmeli)
Karar
Paylasimli veritabani + sorgu filtresi + MQTT topic prefix + API dependency injection stratejisi benimsendi.
Tum tenant'lar ayni veritabani, ayni tablo, ayni EMQX broker ve ayni FastAPI uygulamasini payalsir. Izolasyon uygulama katmaninda saglanir.
Uygulama Detaylari
# FastAPI dependency injection ile tenant izolasyonu
async def get_current_tenant(
current_user: User = Depends(get_current_user)
) -> Tenant:
return current_user.tenant
# Her endpoint'te tenant filtresi
@router.get("/devices")
async def list_devices(
tenant: Tenant = Depends(get_current_tenant),
db: AsyncSession = Depends(get_db)
):
query = select(Device).where(Device.tenant_id == tenant.id)
...
# MQTT ACL kurali (EMQX HTTP backend)
# Her cihaz yalnizca kendi tenant'inin topic'lerine erisebilir
tenant/{tenant_id}/gw/{gateway_id}/# → ALLOW
tenant/{baska_tenant_id}/# → DENY
Alternatifler
Ayri veritabani (Schema-per-tenant)
- Artilari: Guclu izolasyon, tenant bazinda backup/restore, performans izolasyonu
- Eksileri: Migration her tenant icin ayri calistirilmali, baglanti havuzu yonetimi karmasik, operasyonel yuk yuksek
- Red nedeni: 50+ tenant senaryosunda operasyonel maliyeti cok yuksek
Ayri instance (Tenant-per-deployment)
- Artilari: Tam izolasyon, tenant bazinda olcekleme
- Eksileri: Her tenant icin ayri sunucu/container, maliyet cok yuksek, deployment karmasikligi
- Red nedeni: Kucuk-orta olcekli tenant'lar icin maliyet/fayda orani cok dusuk
Row Level Security (PostgreSQL RLS)
- Artilari: Veritabani seviyesinde izolasyon, uygulama katmani hata yapsa bile veri sizintisi onlenir
- Eksileri: TimescaleDB hypertable'larla uyumluluk sorunlari, DEBUG zorlugu, ORM entegrasyonu karmasik
- Red nedeni: TimescaleDB ile RLS uyumlulugu tam olgunlasmanis, debug zorlugu
Gerekce
Secilen strateji su avantajlari sundu:
- Operasyonel basitlik: Tek veritabani, tek deployment, tek migration — yonetim kolayligi
- Olceklenebilirlik: Yeni tenant = veritabanina yeni bir satir — dakikalar icinde aktif
- MQTT ACL ile ag seviyesinde izolasyon: Topic yapisi
tenant/{tid}/ile baslar, EMQX ACL kurallari cihaz bazinda uygulanir - Dusuk maliyet: Tum tenant'lar altyapiyi paylasir — kucuk tenant'lar icin ek maliyet yok
- Dependency injection ile tutarlilik:
get_current_tenant()dependency'si tum endpoint'lerde zorunlu — unutulma riski azalir - Tek codebase: Tum tenant'lar ayni kodu calistirir — hata duzeltme ve ozellik gelistirme tek noktada
Sonuclar
Olumlu
- Yeni tenant olusturma sureci tamamen otomatik ve hizli
- Tek migration tum tenant'lari etkiler — tutarlilik garantisi
- MQTT seviyesinde izolasyon sayesinde ag trafigi bile ayrik
- API seviyesinde dependency injection ile tenant filtresi tutarli sekilde uygulanmakta
- Altyapi maliyeti tenant sayisindan bagimsiz (belirli bir esige kadar)
Olumsuz
- Query'lerde
tenant_idunutulma riski: Dependency injection ile minimize edilmis olsa da, raw SQL veya karmasik sorgularda dikkat gerekir - Noisy neighbor riski: Buyuk bir tenant'in agir sorgulari diger tenant'lari etkileyebilir — query timeout ve rate limiting ile yonetiliyor
- Veri silme karmasikligi: Bir tenant'in tum verisini silmek
CASCADEve coklu tablo taramasi gerektirir - Audit trail: Hangi tenant'in hangi veriye ne zaman eristigi loglanmali — ek logging gerekir