03 Mar 2025·7 menit membaca

Polapola row-level security PostgreSQL untuk aplikasi multi-tenant

Pelajari PostgreSQL row-level security dengan pola praktis untuk isolasi tenant dan aturan peran, sehingga akses ditegakkan di database, bukan hanya di aplikasi.

Polapola row-level security PostgreSQL untuk aplikasi multi-tenant

Mengapa akses yang ditegakkan di database penting di aplikasi bisnis

Aplikasi bisnis biasanya punya aturan seperti “pengguna hanya bisa melihat data perusahaan mereka” dan “hanya manajer yang bisa menyetujui pengembalian dana.” Banyak tim menegakkan aturan itu di UI atau API dan menganggap itu cukup. Masalahnya, setiap jalur tambahan ke database menjadi peluang kebocoran: alat admin internal, pekerjaan latar belakang, kueri analitik, endpoint yang terlupakan, atau bug yang melewatkan satu pemeriksaan.

Isolasi tenant berarti satu pelanggan (tenant) tidak pernah bisa membaca atau mengubah data pelanggan lain, bahkan secara tidak sengaja. Akses berbasis peran berarti orang di dalam tenant yang sama masih memiliki wewenang berbeda, seperti agen vs manajer vs keuangan. Aturan-aturan ini mudah dijelaskan, tapi sulit dijaga konsistensinya ketika tersebar di banyak tempat.

PostgreSQL row-level security (RLS) adalah fitur database yang membuat database yang menentukan baris mana yang dapat dilihat atau diubah oleh sebuah permintaan. Alih-alih berharap setiap kueri di aplikasi Anda mengingat WHERE yang benar, database akan menerapkan kebijakan secara otomatis.

RLS bukanlah pelindung ajaib untuk semua hal. Ia tidak akan merancang skema Anda, menggantikan autentikasi, atau melindungi dari seseorang yang sudah memiliki peran database yang kuat (seperti superuser). Ia juga tidak akan mencegah kesalahan logika seperti “seseorang bisa memperbarui baris yang tidak bisa mereka pilih” kecuali Anda menulis kebijakan untuk baca dan tulis.

Yang Anda dapatkan adalah jaring pengaman yang kuat:

  • Satu set aturan untuk setiap jalur kode yang mengakses database
  • Lebih sedikit momen “ups” saat fitur baru dirilis
  • Audit lebih jelas, karena aturan akses terlihat di SQL
  • Pertahanan lebih baik jika bug API lolos

Ada sedikit biaya pengaturan. Anda perlu cara konsisten untuk meneruskan “siapa pengguna ini” dan “tenant mana” ke database, dan Anda perlu memelihara kebijakan seiring pertumbuhan aplikasi. Hasilnya besar, terutama untuk SaaS dan alat internal di mana data pelanggan sensitif dipertaruhkan.

Dasar Row-Level Security tanpa jargon

Row-Level Security (RLS) secara otomatis memfilter baris mana yang bisa dilihat atau diubah oleh sebuah kueri. Alih-alih bergantung pada setiap layar, endpoint API, atau laporan untuk “mengingat” aturan, database yang akan menerapkannya untuk Anda.

Dengan PostgreSQL row-level security, Anda menulis kebijakan yang diperiksa pada setiap SELECT, INSERT, UPDATE, dan DELETE. Jika kebijakan mengatakan “pengguna ini hanya bisa melihat baris untuk tenant A,” maka halaman admin yang terlupakan, kueri baru, atau hotfix yang terburu-buru tetap mendapat pengaman yang sama.

RLS berbeda dari GRANT/REVOKE. GRANT menentukan apakah sebuah role bisa mengakses tabel sama sekali (atau kolom tertentu). RLS menentukan baris mana di dalam tabel itu yang diizinkan. Dalam praktik, Anda sering menggunakan keduanya: GRANT untuk membatasi siapa yang bisa mengakses tabel, dan RLS untuk membatasi apa yang bisa mereka akses.

RLS juga tahan di dunia nyata yang berantakan. View umumnya mematuhi RLS karena akses ke tabel dasar masih memicu kebijakan. Join dan subquery tetap difilter, jadi pengguna tidak bisa “bergabung” untuk masuk ke data orang lain. Dan kebijakan berlaku tidak peduli klien mana yang menjalankan kueri: kode aplikasi, konsol SQL, pekerjaan latar belakang, atau alat pelaporan.

RLS cocok ketika Anda punya kebutuhan isolasi tenant yang kuat, banyak cara untuk mengkueri data yang sama, atau banyak peran yang berbagi tabel (umum di SaaS dan alat internal). Bisa jadi berlebihan untuk aplikasi kecil dengan satu backend yang dipercaya, atau untuk data yang tidak sensitif dan tidak pernah keluar dari satu layanan terkendali. Saat Anda memiliki lebih dari satu titik masuk (alat admin, ekspor, BI, skrip), RLS biasanya terbayar.

Mulai dengan memetakan tenant, peran, dan kepemilikan data

Sebelum menulis satu kebijakan pun, pastikan siapa yang memiliki apa. PostgreSQL row-level security bekerja paling baik ketika model data Anda sudah mencerminkan tenant, peran, dan kepemilikan.

Mulailah dengan tenant. Di sebagian besar aplikasi SaaS, aturan paling sederhana adalah: setiap tabel bersama yang berisi data pelanggan punya tenant_id. Itu termasuk tabel “jelas” seperti invoices, tapi juga hal yang sering terlupakan, seperti attachments, comments, audit logs, dan background jobs.

Selanjutnya, beri nama peran yang sebenarnya digunakan orang. Jaga setnya kecil dan mudah dimengerti: owner, manager, agent, read-only. Ini adalah peran bisnis yang nantinya Anda petakan ke pemeriksaan kebijakan (bukan sama dengan role database).

Lalu putuskan bagaimana sebuah record dimiliki. Beberapa tabel dimiliki oleh satu pengguna (misalnya, catatan pribadi). Lainnya dimiliki tim (misalnya, inbox bersama). Mencampur keduanya tanpa rencana membuat kebijakan sulit dibaca dan mudah dilanggar.

Cara sederhana mendokumentasikan aturan Anda adalah menjawab pertanyaan yang sama untuk setiap tabel:

  • Apa batas tenant (kolom mana yang menegakkannya)?
  • Siapa yang bisa membaca baris (berdasarkan peran dan kepemilikan)?
  • Siapa yang bisa membuat dan memperbarui baris (dan dalam kondisi apa)?
  • Siapa yang bisa menghapus baris (biasanya aturan paling ketat)?
  • Pengecualian apa yang diizinkan (tim support, otomasi, ekspor)?

Contoh: “Invoices” mungkin mengizinkan manajer melihat semua invoice tenant, agen melihat invoice untuk pelanggan yang ditugaskan, dan pengguna read-only hanya melihat tanpa bisa mengedit. Tentukan sejak awal aturan mana yang harus ketat (isolasi tenant, hapus) dan mana yang bisa fleksibel (visibilitas lebih untuk manajer). Jika Anda membangun di alat no-code seperti AppMaster, pemetaan ini juga membantu menyelaraskan ekspektasi UI dan aturan database.

Pola desain untuk tabel multi-tenant

RLS multi-tenant bekerja paling baik ketika tabel Anda seragam. Jika setiap tabel menyimpan tenant dengan cara berbeda, kebijakan Anda berubah menjadi teka-teki. Bentuk yang konsisten membuat PostgreSQL row-level security lebih mudah dibaca, diuji, dan dipertahankan.

Mulailah dengan memilih satu pengenal tenant dan pakai di mana-mana. UUID umum karena sulit ditebak dan mudah dihasilkan di banyak sistem. Integer juga oke, terutama untuk aplikasi internal. Slug (seperti "acme") ramah manusia, tetapi bisa berubah, jadi anggap itu sebagai field tampilan, bukan kunci inti.

Untuk data yang terikat tenant, tambahkan kolom tenant_id ke setiap tabel yang dimiliki tenant, dan buat NOT NULL bila memungkinkan. Jika sebuah baris dapat ada tanpa tenant, itu biasanya tanda masalah. Sering berarti Anda mencampur data global dan tenant dalam satu tabel, yang membuat kebijakan RLS lebih sulit dan rapuh.

Indexing sederhana tapi penting. Sebagian besar kueri di aplikasi SaaS memfilter berdasarkan tenant terlebih dulu, lalu field bisnis seperti status atau tanggal. Default yang baik adalah index pada tenant_id, dan untuk tabel dengan trafik tinggi gunakan index komposit seperti (tenant_id, created_at) atau (tenant_id, status) berdasarkan filter umum Anda.

Putuskan sejak awal tabel mana yang global dan mana yang tenant-scoped. Tabel global umum termasuk countries, currency codes, atau plan definitions. Tabel tenant-scoped termasuk customers, invoices, tickets, dan apa pun yang dimiliki tenant.

Jika Anda ingin aturan yang tetap mudah dipelihara, jaga sempit:

  • Tabel tenant-scoped: tenant_id NOT NULL, RLS diaktifkan, kebijakan selalu memeriksa tenant_id.
  • Tabel referensi global: tidak ada tenant_id, tidak ada kebijakan tenant, baca-saja untuk sebagian besar peran.
  • Tabel bersama tapi terkontrol: pisahkan tabel per konsep (hindari mencampur baris global dan tenant).

Jika Anda membangun dengan alat seperti AppMaster, konsistensi ini juga bermanfaat di model data. Setelah tenant_id menjadi field standar, Anda bisa memakai pola yang sama di banyak modul tanpa kejutan.

Langkah demi langkah: buat kebijakan tenant pertama Anda

Bangun alat internal yang aman
Buat faktur, tiket, dan layar admin dengan pelindung yang selaras dengan aturan database Anda.
Coba Sekarang

Kemenangan awal yang baik dengan PostgreSQL row-level security adalah satu tabel yang hanya dapat dibaca di dalam tenant saat ini. Intinya sederhana: bahkan jika seseorang lupa WHERE di API, database menolak mengembalikan baris dari tenant lain.

Mulailah dengan tabel yang menyertakan kolom tenant_id:

ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;

Setelah RLS diaktifkan, perilaku default sering mengejutkan orang: jika sebuah role tunduk pada RLS dan tidak ada kebijakan yang cocok, SELECT mengembalikan nol baris (dan write gagal). Itulah yang Anda inginkan di awal.

Sekarang tambahkan kebijakan baca minimal. Contoh ini mengasumsikan aplikasi Anda mengatur variabel session seperti app.tenant_id setelah login:

CREATE POLICY invoices_tenant_read
ON invoices
FOR SELECT
USING (tenant_id = current_setting('app.tenant_id')::uuid);

Selanjutnya, tambahkan aturan tulis. Dalam RLS, USING mengontrol baris yang sudah ada yang boleh Anda sentuh, dan WITH CHECK mengontrol nilai baru yang diizinkan untuk ditulis.

CREATE POLICY invoices_tenant_insert
ON invoices
FOR INSERT
WITH CHECK (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY invoices_tenant_update
ON invoices
FOR UPDATE
USING (tenant_id = current_setting('app.tenant_id')::uuid)
WITH CHECK (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY invoices_tenant_delete
ON invoices
FOR DELETE
USING (tenant_id = current_setting('app.tenant_id')::uuid);

Kebijakan bersifat PERMISSIVE secara default, artinya salah satu kebijakan dapat mengizinkan akses. Pilih RESTRICTIVE ketika Anda ingin aturan yang harus semuanya lolos (berguna untuk menambahkan penjaga kedua seperti “hanya akun aktif”).

Jaga kebijakan kecil dan berfokus pada peran. Alih-alih satu aturan besar dengan banyak OR, buat kebijakan terpisah per audiens (misalnya, invoices_tenant_read_app_user dan invoices_tenant_read_support_agent). Lebih mudah diuji, lebih mudah direview, dan lebih aman untuk diubah nanti.

Meneruskan konteks tenant dan pengguna dengan aman

Agar PostgreSQL row-level security bekerja, database perlu tahu “siapa yang memanggil” dan “tenant mana yang mereka miliki.” Kebijakan RLS hanya bisa membandingkan baris dengan nilai yang bisa dibaca database saat runtime, jadi Anda harus meneruskan konteks itu ke session.

Polanya umum adalah mengatur variabel session setelah autentikasi, lalu biarkan kebijakan membacanya dengan current_setting(). Aplikasi memverifikasi identitas (misalnya dengan memvalidasi JWT), lalu menulis tenant dan user ID ke koneksi database.

-- Run once per request (or per transaction)
SELECT set_config('app.tenant_id', '3f2a0c3e-9c7b-4d3f-9c5c-3c5e9c5d1a11', true);
SELECT set_config('app.user_id',   '8d9c6b1a-6b6d-4e32-9c0d-2bfe6f6c1111', true);
SELECT set_config('app.role',      'support_agent', true);

-- In a policy
-- tenant_id column is a UUID
USING (tenant_id = current_setting('app.tenant_id', true)::uuid);

Menggunakan argumen ketiga true membuatnya “lokal” untuk transaksi saat ini. Itu penting jika Anda menggunakan connection pooling: koneksi yang dipooling bisa digunakan ulang oleh permintaan lain, jadi Anda tidak ingin konteks tenant kemarin tetap menempel.

Mengisi konteks dari klaim JWT

Jika API Anda memakai JWT, perlakukan klaim sebagai input, bukan kebenaran mutlak. Verifikasi tanda tangan token dan expiry terlebih dahulu, lalu salin hanya field yang Anda butuhkan (tenant_id, user_id, role) ke setting session. Hindari membiarkan klien mengirim nilai ini langsung sebagai header atau query param.

Konteks hilang atau tidak valid: tolak secara default

Rancang kebijakan sehingga setting yang hilang menghasilkan nol baris.

Gunakan current_setting('app.tenant_id', true) sehingga nilai yang hilang mengembalikan NULL. Cast ke tipe yang tepat (misalnya ::uuid) sehingga format yang tidak valid gagal cepat. Dan gagalkan permintaan jika konteks tenant/user tidak bisa diset, daripada menebak default.

Ini menjaga kontrol akses konsisten bahkan ketika kueri melewati UI atau endpoint baru ditambahkan nanti.

Pola peran praktis yang mudah dipelihara

Pindah dari prototipe ke produksi
Deploy ke AppMaster Cloud atau cloud Anda sendiri saat siap go-live.
Deploy

Cara termudah menjaga kebijakan PostgreSQL row-level security tetap terbaca adalah memisahkan identitas dari izin. Baseline yang baik adalah tabel users ditambah tabel memberships yang menghubungkan user ke tenant dan peran (atau beberapa peran). Lalu kebijakan Anda bisa menjawab satu pertanyaan: “Apakah pengguna saat ini punya membership yang tepat untuk baris ini?”

Pertahankan nama peran yang terkait tindakan nyata, bukan jabatan. “invoice_viewer” dan “invoice_approver” cenderung lebih tahan lama daripada “manager,” karena kebijakan bisa ditulis dalam kata-kata yang jelas.

Berikut beberapa pola peran yang tetap sederhana saat aplikasi berkembang:

  • Owner-only: baris punya created_by_user_id (atau owner_user_id) dan akses memeriksa kecocokan tepat.
  • Team-only: baris punya team_id, dan kebijakan memeriksa pengguna adalah anggota tim itu dalam tenant yang sama.
  • Approved-only: baca diizinkan hanya ketika status = 'approved', dan tulis dibatasi untuk approver.
  • Mixed rules: mulai ketat, lalu tambahkan pengecualian kecil (misalnya, “support bisa membaca, tapi hanya dalam tenant”).

Cross-tenant admins sering membuat tim bermasalah. Tangani mereka secara eksplisit, bukan sebagai pintasan “superuser” tersembunyi. Buat konsep terpisah seperti platform_admin (global) dan minta pengecekan yang disengaja dalam kebijakan. Lebih baik lagi, batasi akses lintas-tenant baca-saja secara default dan buat tulis memerlukan persyaratan lebih tinggi.

Dokumentasi lebih penting dari yang tampak. Taruh komentar pendek di atas setiap kebijakan yang menjelaskan niat, bukan SQL. “Approvers can change status. Viewers can only read approved invoices.” Enam bulan kemudian, catatan itu yang menjaga perubahan kebijakan tetap aman.

Jika Anda membangun dengan alat no-code seperti AppMaster, pola ini tetap berlaku. UI dan API Anda bisa bergerak cepat, tapi aturan database tetap stabil karena bergantung pada memberships dan arti peran yang jelas.

Contoh skenario: SaaS sederhana dengan invoices dan support

Taruh dasar identitas dengan benar
Gunakan modul siap pakai seperti authentication untuk meneruskan konteks pengguna dan tenant secara konsisten melalui aplikasi Anda.
Atur Auth

Bayangkan SaaS kecil yang melayani banyak perusahaan. Setiap perusahaan adalah tenant. Aplikasi punya invoices (uang) dan support tickets (bantuan sehari-hari). Pengguna bisa menjadi agent, manager, atau support.

Model data (disederhanakan): setiap baris invoice dan ticket punya tenant_id. Tickets juga punya assignee_user_id. Aplikasi mengatur tenant dan user saat ini di session database segera setelah login.

Begini bagaimana PostgreSQL row-level security mengubah risiko sehari-hari.

Seorang pengguna dari Tenant A membuka layar invoices dan mencoba menebak ID invoice dari Tenant B (atau UI mengirimkannya secara tidak sengaja). Kueri tetap dijalankan, tetapi database mengembalikan nol baris karena kebijakan mengharuskan invoice.tenant_id = current_tenant_id. Tidak ada kebocoran “akses ditolak”, hanya hasil kosong.

Di dalam satu tenant, peran mempersempit akses lebih jauh. Seorang manajer bisa melihat semua invoices dan tickets tenant mereka. Seorang agen hanya bisa melihat tickets yang ditugaskan pada mereka, plus mungkin draft mereka sendiri. Di sinilah tim sering salah di API, terutama ketika filter bersifat opsional.

Support adalah kasus khusus. Mereka mungkin perlu melihat invoices untuk membantu pelanggan, tetapi tidak boleh mengubah field sensitif seperti amount, bank_account, atau tax_id. Pola praktis adalah:

  • Izinkan SELECT pada invoices untuk peran support (tetap dalam cakupan tenant).
  • Izinkan UPDATE hanya melalui jalur “aman” (misalnya, view yang mengekspos kolom yang bisa diedit, atau kebijakan update ketat yang menolak perubahan pada field yang dilindungi).

Sekarang skenario “bug API tidak sengaja”: sebuah endpoint lupa menerapkan filter tenant selama refactor. Tanpa RLS, itu bisa membocorkan invoices lintas-tenant. Dengan RLS, database menolak mengembalikan baris di luar tenant session, jadi bug hanya menghasilkan layar yang rusak, bukan kebocoran data.

Jika Anda membangun SaaS semacam ini di AppMaster, Anda tetap menginginkan aturan ini di database. Pemeriksaan UI membantu, tapi aturan database yang menahan saat sesuatu terlewat.

Kesalahan umum dan cara menghindarinya

PostgreSQL row-level security kuat, tetapi slip kecil bisa diam-diam mengubah “aman” menjadi “mengejutkan.” Kebanyakan masalah muncul saat tabel baru ditambahkan, peran berubah, atau seseorang mengetes dengan user database yang salah.

Kegagalan umum adalah lupa mengaktifkan RLS pada tabel baru. Anda mungkin menulis kebijakan hati-hati untuk tabel inti, lalu menambahkan tabel “notes” atau “attachments” kemudian mengirimkannya dengan akses penuh. Jadikan kebiasaan: tabel baru berarti RLS diaktifkan, plus setidaknya satu kebijakan.

Perangkap sering lain adalah kebijakan yang tidak konsisten antar aksi. Kebijakan yang mengizinkan INSERT tapi memblok SELECT bisa terlihat seperti “data menghilang” segera setelah dibuat. Sebaliknya juga menyakitkan: pengguna bisa membaca baris yang tidak bisa mereka buat, jadi mereka mengakali di UI. Pikirkan alur: “create then view,” “update then re-open,” “delete then list.”

Berhati-hatilah dengan fungsi SECURITY DEFINER. Mereka berjalan dengan hak pemilik fungsi, yang dapat mem-bypass RLS jika Anda tidak ketat. Jika menggunakannya, buat kecil, validasi input, dan hindari dynamic SQL kecuali benar-benar diperlukan.

Juga hindari mengandalkan filter di sisi aplikasi sambil membiarkan akses database terbuka. Bahkan API yang dibangun dengan baik akan menambah endpoint baru, pekerjaan latar belakang, dan skrip admin. Jika role database bisa membaca semuanya, suatu saat sesuatu akan bocor.

Untuk menangkap masalah lebih awal, jaga pemeriksaannya praktis:

  • Uji menggunakan role DB yang sama seperti yang digunakan aplikasi produksi, bukan user admin pribadi Anda.
  • Tambahkan satu tes negatif per tabel: pengguna dari tenant lain harus melihat nol baris.
  • Pastikan setiap tabel mendukung aksi yang Anda harapkan: SELECT, INSERT, UPDATE, DELETE.
  • Tinjau penggunaan SECURITY DEFINER dan dokumentasikan mengapa diperlukan.
  • Sertakan “RLS enabled?” dalam checklist review kode dan migrasi.

Contoh: jika agen support membuat catatan invoice tapi tidak bisa membacanya kembali, seringkali itu kebijakan INSERT tanpa SELECT yang cocok (atau konteks tenant tidak diset untuk session itu).

Daftar periksa cepat untuk memvalidasi setup RLS Anda

Tempatkan aturan bisnis di satu tempat
Ubah peran, kepemilikan, dan persetujuan menjadi logika backend tanpa menulis ulang pemeriksaan otorisasi di mana-mana.
Buat Proyek

Row-Level Security bisa tampak benar saat review dan tetap gagal di penggunaan nyata. Validasi lebih tentang mencoba merusaknya dengan akun dan kueri realistis daripada membaca kebijakan saja. Ujilah seperti cara aplikasi Anda akan menggunakannya, bukan seperti yang Anda harapkan.

Buat satu set identitas uji kecil terlebih dahulu. Pakai minimal dua tenant (Tenant A dan Tenant B). Untuk tiap tenant, tambahkan user normal dan peran admin atau manager. Jika Anda mendukung peran “support agent” atau “read-only,” tambahkan juga.

Lalu tekan PostgreSQL row-level security dengan serangkaian pemeriksaan kecil dan dapat diulang:

  • Jalankan operasi inti untuk tiap peran: daftar baris, ambil satu baris berdasarkan id, insert, update, dan delete. Untuk tiap operasi, coba kasus “diizinkan” dan “harus diblokir.”
  • Buktikan batas tenant: sebagai Tenant A, coba baca atau ubah data Tenant B menggunakan id yang Anda tahu ada. Anda harus mendapatkan nol baris kembali atau error permission, bukan “beberapa baris.”
  • Uji join untuk kebocoran: gabungkan tabel terlindungi dengan tabel lain (termasuk lookup). Konfirmasi join tidak menarik baris terkait dari tenant lain lewat foreign key atau view.
  • Periksa konteks hilang atau salah menolak akses: hapus konteks tenant/user (apa pun yang aplikasi Anda set per request) dan ulangi. “Tanpa konteks” harus gagal tertutup. Coba juga tenant id yang tidak valid.
  • Konfirmasi performa dasar: lihat explain plans dan pastikan index mendukung pola filter tenant Anda (umumnya tenant_id plus apa pun yang Anda sort atau cari).

Jika ada tes yang mengejutkan, perbaiki kebijakan atau cara pengaturan konteks dulu. Jangan menambalnya di UI atau API dan berharap aturan database akan “hampir selalu bertahan.”

Langkah selanjutnya: gulirkan dengan aman dan jaga konsistensi

Perlakukan PostgreSQL row-level security seperti sistem keselamatan: perkenalkan secara hati-hati, verifikasi sering, dan jaga aturan cukup sederhana sehingga tim Anda mengikutinya.

Mulailah kecil. Pilih tabel di mana kebocoran paling merugikan (payments, invoices, HR data, customer messages), dan aktifkan RLS di sana dulu. Kemenangan awal lebih baik daripada rollout besar yang tak seorang pun benar-benar mengerti.

Urutan rollout praktis sering terlihat seperti ini:

  • Tabel inti “owned” dulu (baris jelas milik satu tenant)
  • Tabel yang berisi data pribadi (PII)
  • Tabel yang dibagikan tapi difilter oleh tenant (reports, analytics)
  • Tabel join dan kasus tepi (many-to-many relationships)
  • Sisanya setelah dasar stabil

Jadikan pengujian tidak opsional. Tes otomatis harus menjalankan kueri yang sama sebagai tenant dan peran berbeda dan memastikan apa yang berubah. Sertakan pemeriksaan “harus mengizinkan” dan “harus menolak”, karena bug paling mahal adalah over-permission yang diam-diam.

Pertahankan satu tempat jelas dalam alur request Anda di mana konteks session diset sebelum kueri apa pun berjalan. Tenant id, user id, dan role harus diterapkan sekali, dini, dan tidak pernah ditebak lagi. Jika Anda mengatur konteks di tengah transaksi, Anda akan suatu saat menjalankan kueri dengan nilai yang hilang atau usang.

Saat membangun dengan AppMaster, rencanakan konsistensi antara API backend yang dihasilkan dan kebijakan PostgreSQL Anda. Standarkan bagaimana konteks tenant dan peran diteruskan ke database (misalnya, variabel session yang sama untuk setiap endpoint) sehingga kebijakan berperilaku sama di mana-mana. Jika Anda menggunakan AppMaster di appmaster.io, RLS tetap layak diperlakukan sebagai otoritas akhir untuk isolasi tenant, meskipun Anda juga membatasi akses di UI.

Akhirnya, amati apa yang gagal. Kegagalan otorisasi adalah sinyal berguna, terutama setelah rollout. Lacak penolakan berulang dan selidiki apakah itu tanda serangan nyata, alur klien yang rusak, atau kebijakan yang terlalu ketat.

Daftar kebiasaan singkat yang membantu RLS tetap sehat:

  • Pola default-deny, dengan pengecualian ditambahkan secara sengaja
  • Nama kebijakan yang jelas (table + action + audience)
  • Perubahan kebijakan direview seperti perubahan kode
  • Penolakan dicatat dan ditinjau selama rollout awal
  • Set tes kecil ditambahkan untuk setiap tabel baru dengan RLS
Mudah untuk memulai
Ciptakan sesuatu yang menakjubkan

Eksperimen dengan AppMaster dengan paket gratis.
Saat Anda siap, Anda dapat memilih langganan yang tepat.

Memulai