Multi-tenancy adalah janji sederhana dengan konsekuensi panjang: banyak perusahaan memakai satu aplikasi, dan data mereka tidak boleh saling terlihat — bukan kadang-kadang, tapi selalu. Ini pola yang saya pakai di dua sistem production (Dexova dan Helixio), plus jebakan yang saya temui.
Pilih model isolasinya secara sadar
Ada tiga pilihan umum: database terpisah per tenant, skema terpisah per tenant, atau satu skema bersama dengan kolom tenant. Untuk SaaS dengan banyak tenant kecil–menengah, skema bersama hampir selalu titik mulai yang benar: operasional paling murah, migrasi sekali jalan, dan kapasitas tenant baru praktis gratis.
Harganya: isolasi sepenuhnya menjadi tanggung jawab disiplin aplikasi. Setiap query harus dibatasi tenant — dan 'setiap' di sini benar-benar berarti setiap.
Tenant context yang tidak bisa lupa
Kesalahan klasik: mengandalkan setiap developer untuk ingat menambahkan filter tenant di query. Sekali lupa, data bocor. Konteks tenant harus mengalir dari autentikasi ke seluruh jalur eksekusi — di Go, lewat context.Context yang diisi middleware setelah token divalidasi, lalu dibaca lapisan data.
Prinsipnya: jalur yang aman harus menjadi jalur yang paling mudah. Query helper yang menerima tenant dari context secara eksplisit membuat 'lupa filter' berubah dari bug diam-diam menjadi kode yang terlihat janggal saat review.
RBAC di atas isolasi, bukan sebagai gantinya
Isolasi tenant menjawab 'data perusahaan mana' — belum menjawab 'siapa boleh apa'. Di Helixio saya memakai empat peran (Owner, Admin, Member, Viewer) per workspace; di Dexova, peran per modul (mis. kasir vs manajer di POS, dengan pencabutan akses dari dashboard).
Keduanya lapisan berbeda dan jangan dicampur: cek tenant terjadi di lapisan data, cek permission di lapisan use-case. Mencampurnya membuat keduanya sulit diuji.
Jebakan yang baru terasa belakangan
- Background job: job async tidak punya request — konteks tenant harus dibawa eksplisit di payload job, bukan diambil dari 'user yang sedang login'.
- Cache key: key tanpa prefix tenant adalah kebocoran data yang menunggu jadwal. Semua key di-namespace per tenant.
- Data global vs tenant: tabel referensi (mis. daftar bank, hari libur) sengaja global — tandai jelas mana yang global supaya tidak ada yang 'memperbaikinya' dengan menambah kolom tenant.
- Export dan laporan: jalur yang paling sering menggabungkan banyak query — dan tempat paling umum satu filter terlewat. Uji isolasi justru paling penting di sini.
Ringkasan
Multi-tenancy bukan fitur, tapi properti yang harus dijaga oleh arsitektur: konteks tenant yang mengalir otomatis, jalur aman yang paling mudah dipakai, dan kecurigaan sehat pada semua jalur yang tidak melewati request — job, cache, dan laporan.