Ana Sayfa / Blog / Multi-tenant data export/import: GDPR ve KVKK ile uyum

Multi-tenant data export/import: GDPR ve KVKK ile uyum

Kullanıcının verisini export etme ve silme hakkı regülasyon şartı. Multi-tenant sistemde bu nasıl tasarlanıyor, data leak riski olmadan?

GDPR ve KVKK iki hakkı kullanıcıya veriyor: right to access (verimin kopyasını ver) ve right to erasure (verimi sil). Multi-tenant bir SaaS’ta bu feature’ları implement etmek sanılandan karmaşık.

2 B2B SaaS projede data export/import feature’larını kurdum. Tuzaklar, pattern’lar, regulatory compliance notları.

Yasal bağlam

GDPR (AB): Article 15 (right to access), Article 17 (right to erasure), Article 20 (right to data portability). 30 gün içinde yanıt zorunlu.

KVKK (Türkiye): benzer haklar. Aynı zamanda 10 yıl bazı kategoriler için retention.

Müşteri verisini export edebilmeli, sil diyebilmeli. Bu feature’lar yoksa yasal risk ciddi.

Multi-tenant karmaşıklığı

Single-tenant’ta kolay: “user_id X’in tüm verisini ver”. Join, export, done.

Multi-tenant’ta karmaşık:

  • User birden fazla tenant’ta olabilir (personal + company workspace)
  • User’ın verileri hangi tenant’a ait?
  • Tenant admin kendi tenant’ı için export talep edebiliyor (tüm user data)
  • Tenant sil ise tenant admin yetkisi ile, user’lar onay vermedi mi?
  • Shared resource’lar (example: user A’nın comment’i user B’nin document’ında)

Bu ilişkiler export/erasure scope’unu belirlemeyi zorlaştırıyor.

Export tasarımı

İlk karar: kim export talep ediyor, ne scope’ta?

User-initiated: “benim verilerimi indir”. Scope: user’ın kendisine ait data.

Tenant admin-initiated: “tenant’ın tüm verisini indir”. Scope: tenant ownership’i var.

System backup: internal, migration, not user-facing.

Her birinin policy’si farklı.

Scope definition

User data neyi içeriyor? Her entity için karar:

User entity:
- profile (name, email, avatar): direct user data, EXPORT
- comments: user'ın yazdığı, EXPORT
- documents authored: user'ın yarattığı, EXPORT
- documents collaborated on: other user'ın doc'unda yorum, EXPORT (their comments only)
- logs (login, action history): user activity, EXPORT
- system metadata (created_at, roles): EXPORT
- payment info: LIMITED (last 4 of CC OK, full PAN no)
- sessions: not useful to export, SKIP

Bu karar tablosunu her entity için yap. Compliance + usefulness dengesi.

Format: JSON + file attachments

Standart format yok. GDPR “machine-readable” diyor, çoğu şirket JSON + attached files:

export.zip
├── profile.json
├── comments.json
├── documents/
│   ├── doc-1.json
│   ├── doc-1-attachment-1.pdf
│   └── ...
├── activity-log.csv
└── README.txt (bu archive'ı nasıl okumalı)

JSON primary format, CSV optional (spreadsheet friendly), binary file attachments, README ile açıklama.

Export pipeline

  1. User request submit ediyor (UI veya API)
  2. Request queue’ya düşüyor
  3. Worker user’ın tüm data’sını query’liyor
  4. JSON + attachments bir ZIP’e packageliyor
  5. Private S3 bucket’a upload (short-lived signed URL)
  6. Email ile download link kullanıcıya
  7. Link 7 gün geçerli (security)
  8. User download edince access log’lanıyor
@queue.task
def export_user_data(user_id, request_id):
    data = gather_user_data(user_id)
    zip_path = create_export_zip(data)
    s3_url = upload_to_private_bucket(zip_path, expires=7*24*60*60)
    send_email(user_id, 'export_ready', {'url': s3_url})
    mark_request_completed(request_id)

Büyük export (GB seviyesinde) saatler sürebilir. Progress tracking UI.

Shared data problemi

Kullanıcı A workspace içinde document yarattı, B o document’a comment ekledi. A’nın export’u ne içersin?

  • A’nın document’ı: dahil
  • B’nin comment’i A’nın doc’unda: dahil ama “by user B” metadata ile
  • B’nin kişisel bilgisi: NOT included (only user ID referans)

B’nin kimliği expose edilmiyor. Reference ID’sı varsa onun için ayrı lookup gerekli.

Erasure: daha zor

Silme export’tan zor. User A sildi:

  • A’nın profile: DELETE
  • A’nın sadece kendine ait doc: DELETE
  • A’nın shared doc’larda comment: ANONYMIZE (“deleted user” olarak kalsın, doc integrity bozulmasın)
  • A’nın diğer user’ın doc’una ettiği edit: historical record (audit log), ANONYMIZE
  • A’nın payment transaction: retain (regulation: 7 yıl finansal kayıt)
  • A’nın support ticket’ları: ANONYMIZE (transcript kalacak, user info silinecek)
  • A’nın aggregate analytics: aggregate kalabiliyor, individual track silinecek

Hard delete everywhere compliance ile çelişiyor. Anonymization pattern yaygın.

Anonymization pattern

def anonymize_user(user_id):
    user = User.get(user_id)
    user.email = f"deleted-{user_id}@anonymous.local"
    user.name = "Deleted User"
    user.avatar_url = None
    user.phone = None
    user.status = "deleted"
    user.deleted_at = now()
    user.save()
    
    # Related data
    Comment.where(user_id=user_id).update(display_name="Deleted User")
    Document.where(author_id=user_id).update(author_display="Deleted User")
    
    # Full delete for some
    Session.where(user_id=user_id).delete()
    NotificationPreference.where(user_id=user_id).delete()
    
    # Audit
    AuditLog.insert({
        'action': 'user_erased',
        'user_id': user_id,
        'reason': 'user_request',
        'timestamp': now()
    })

Bu pattern data integrity koruyor (doc’un author’u null değil), PII siliyor.

Retention policy: bazı data kalsın

KVKK ve GDPR hepsini sildirmiyor. “Legitimate interest” altında tutulabilenler:

  • Payment records (anti-fraud, vergi)
  • Audit trail (compliance)
  • Aggregated analytics (personalization’dan arındırılmış)

Erasure request’inde şu response pattern’ı:

Verilerinizin silinmesi tamamlandı. Aşağıdaki veriler yasal zorunluluk nedeniyle retain ediliyor:
- Ödeme kayıtları (7 yıl - vergi)
- Denetim kayıtları (10 yıl - regulation)
- Anonimize edilmiş kullanım istatistikleri

Bu verilerde sizi tanımlayabilecek bilgi yok.

Şeffaflık + compliance.

Tenant sil ise

Tenant admin “tenant’ı sil” diyor. User’lar var tenant’ta.

Seçenekler:
1. Tenant silme sırasında user’ların verisini de sil (otomatik erasure)
2. Tenant silme 30 gün gecikmeli, user’lara bildirim gidiyor, isteyen data’sını export ediyor
3. Tenant soft delete, user’lar migrate olabilir

Ben option 2 pattern’ını tercih ediyorum. Kullanıcı uyarı aldıktan sonra karar verebilir.

Data portability: export format standard?

GDPR article 20 “data portability” istiyor. Data başka servise taşınabilir format’ta olmalı.

Pratikte standart format yok. Slack, Google Docs, Notion her biri farklı format export ediyor. Taşınabilirlik teorik.

Common format alternatifleri:
– JSON generic
– CSV spreadsheet
– ICS calendar
– PDF documents
– EML email

Kendi format’ında export ver, README ile explain et. Başka servis manuel import edebilir.

Admin UI: request management

Data request’leri track etmek için admin panel şart:

  • Liste: pending, in progress, completed, failed
  • Details: requester, requested_at, scope, status
  • Action: approve (manual review gerekliyse), rerun (failed export), mark complete
  • Audit: kim yaptı, ne zaman

Compliance officer’lar için ayrı view: son 30 gündeki tüm request’ler, SLA (30 gün response time) compliant mı.

SLA tracking

GDPR 30 gün diyor. 30 günde response vermek zorunlu:

  • T+0: request received
  • T+1: acknowledgment email (“talebiniz alındı”)
  • T+1..T+25: processing
  • T+25: if not complete, escalate (internal alert)
  • T+30: hard deadline

Alert rules 25. günde tetikleniyor. Compliance risk’i önleniyor.

Test: dummy user scenarios

Data erasure test etmek zor. Test approach:

  1. Test environment’ta fake user yarat (realistic data ile)
  2. Export run
  3. Export content’i verify (tüm expected data var mı)
  4. Erasure run
  5. DB’de user referrable mı kontrol
  6. Query: SELECT * FROM any_table WHERE references_user_id = X – sonuç boş olmalı veya anonymized

Bu test suite her feature deploy’unda koşuyor. Regression: yeni feature eklendiğinde user data oluşturabiliyor ama erasure’ye entegre olmamış olabilir.

Son tavsiye

Data export/erasure regulatory zorunluluk ama aynı zamanda kullanıcı güven alameti. İyi implementation:

  1. Entity-by-entity scope tanımla
  2. Export format JSON + attachments ZIP
  3. Erasure = anonymization (full delete’ten değil)
  4. Retention policy transparency
  5. Admin UI ile SLA tracking
  6. Continuous test disciplin

Bu 6 madde compliance’ı karşılıyor, kullanıcı güveni kazandırıyor, legal risk minimize ediyor. Production’da ihmali olan ekipler regulatory denetim sırasında ciddi kayıplar yaşayabilir.

Bu konuda bir projeniz mi var?

Kısa bir özet bırakın, 24 saat içinde size dönüş yapayım.

İletişime Geç