Postgres Row Level Security (RLS) Policy Generator
Describe your table and isolation model and get a complete, runnable row level security script: ALTER TABLE ... ENABLE ROW LEVEL SECURITY, one CREATE POLICY per command with the correct USING and WITH CHECK expressions, the GRANT statements RLS still depends on, a supporting index, session-variable usage examples and a matching rollback script. Everything is generated in your browser — no schema or connection details leave the page.
Do more than postgres row level security (rls) policy generator — meet Chat2DB
Chat2DB is an AI-powered SQL client for Windows, macOS and Linux. Write SQL in natural language, format and optimize queries automatically, and manage MySQL, PostgreSQL, Oracle and 20+ other databases in one workspace.
How to use
- Enter the schema, table and the role your application connects as, then pick an isolation strategy: session-variable multi-tenancy, per-row owner, or role-based.
- Set the tenant or owner column, choose which commands to cover, and decide whether to FORCE RLS on the owner and add a supporting index.
- Copy the policy script and run it as the table owner, then use the verification queries to confirm pg_policies matches what you expect.
Frequently asked questions
What is the difference between USING and WITH CHECK in a Postgres RLS policy?
USING filters rows that already exist: it is applied to SELECT, UPDATE and DELETE to decide which rows the role can see or touch. WITH CHECK validates rows after they are written, so it applies to INSERT and to the new version of a row in UPDATE. A policy FOR INSERT accepts only WITH CHECK, and FOR SELECT or FOR DELETE accepts only USING. If you write an UPDATE policy with USING but no WITH CHECK, a user can move a row out of their own partition — this generator emits both expressions for UPDATE to prevent that.
Why does row level security not apply to my table owner?
By default PostgreSQL exempts the table owner and any superuser from RLS, which is convenient for migrations but surprising if your application connects as the owner. ALTER TABLE ... FORCE ROW LEVEL SECURITY makes the policies apply to the owner too. The safer pattern is to keep the owner separate and have the application log in as a dedicated, non-owner role such as app_user, then grant only the privileges it needs.
Does row level security slow down queries?
The policy expression is added to every query as an extra predicate, so an unindexed tenant_id turns each read into a sequential scan. Index the column the policy filters on, keep the expression simple, and prefer current_setting() over a subquery against another table — a subquery in a policy is re-evaluated per row unless it can be inlined. Use EXPLAIN (ANALYZE, BUFFERS) to see the injected filter. Chat2DB, a free AI-powered database client, renders execution plans visually so the effect of a policy is easy to spot: download it at https://chat2db.ai/download or use the web version at https://app.chat2db.ai.
