PreviewRustaBase OSS is in public preview. Build on managed PostgreSQL with APIs, authentication, storage, realtime, and server-side functions.Read the product direction

Functions and configuration

Row-level security

Row-level security (RLS) lets PostgreSQL decide which rows each user can read or change. The database enforces it, so it applies to every API call, SDK, and realtime subscription.

How it fits with API rules

Tables have API rules for list, view, create, update, and delete. RLS policies run beneath those rules, inside PostgreSQL. Use both: API rules for the simple cases, and RLS as a second layer that holds even if a rule is too loose.

Turn on RLS and add a policy

  1. Open your Project and select Row-level security.
  2. Pick a table and switch it from RLS off to RLS on. With no policies, nobody except the service role can read the table.
  3. Select New policy and give it a name, such as Owners can read their orders.
  4. Choose the command: SELECT, INSERT, UPDATE, DELETE, or all.
  5. Choose the roles: Anonymous, Authenticated, or Service role.
  6. Write the USING expression, which decides which existing rows the user can see or change.
  7. For INSERT and UPDATE, write the WITH CHECK expression, which decides which new values are allowed.
  8. Select Preview SQL to review the statement, then Save policy.

Common policies

GoalCommandExpression
Users read only their own rowsSELECTUSING owner = auth.uid()
Users create rows for themselvesINSERTWITH CHECK owner = auth.uid()
Users edit only their own rowsUPDATEUSING owner = auth.uid(), WITH CHECK owner = auth.uid()
Everyone reads published postsSELECTUSING status = 'published'

Test before you ship

Use Test access with a real test user ID to see exactly which rows that user can reach. Try an anonymous visitor, a signed-in user, the owner, and an administrator.

await rb.admin.rls.setEnabled("orders", { enabled: true });
await rb.admin.rls.createPolicy("orders", {
  name: "owners_read",
  command: "SELECT",
  roles: ["authenticated"],
  using: "owner = auth.uid()",
});
const result = await rb.admin.rls.test({ table: "orders", userId: "USER_ID" });

Good practice

  • Start with everything denied and add the smallest access each group needs.
  • Store administrator roles in their own table, never on the user's profile where users could edit them.
  • Do not query a protected table from its own policy. Use a helper function for role checks instead, or the policy can loop.
  • Index the columns your policies filter on, such as owner.

Configure Project settings

Found something wrong on this page?

Fix it yourself. The link below opens this file in GitHub's editor and forks the repository for you if you need one, and your change becomes a pull request without leaving the browser.