Skip to content

Data security

Bubble privacy rules → Postgres row-level security

Privacy rules are what keep one user’s data away from another in Bubble. When you move to Supabase, the same job is done by row-level security in Postgres — mostly one-to-one, with a few differences worth knowing.

By The deBub teamPublished 5 min read

On this page

The short version

  • A Bubble privacy rule is a condition plus permissions on a data type; Postgres row-level security (RLS) is a condition on a table. Most rules translate directly.
  • Bubble’s rules add up and “Everyone else” only applies when no other rule matches — the read policy has to reproduce exactly that.
  • RLS works on whole rows. Rules that hide individual fields need a view or a server function instead — a converter should tell you where that happens, not silently expose the fields.

01Two ways of saying “who can see this”

In Bubble, privacy rules are “conditions you set up on each data type” (Bubble manual). They run on Bubble’s server, so data a user may not see never reaches their browser. Rules are additive: a user gets every permission of every rule they match, and the built-in “Everyone else” rule covers whoever matches none of them.

Postgres has the same idea built in. With row-level security switched on, a table returns only the rows for which a policy’s condition is true for the current user. Supabase passes the signed-in user to Postgres, so a condition like “this row belongs to me” is one line of SQL.

02How the pieces map

Bubble privacy rules and their Postgres RLS counterparts
BubblePostgres / SupabaseNotes
Rule condition, e.g. “This Thing’s Creator is Current User”A policy condition, e.g. created_by = auth.uid()Direct
Several rules on one typeOne read policy whose conditions are joined with ORSame additive result
“Everyone else”An extra branch: allowed only when none of the other conditions are trueMust not be a plain OR, or it widens access
View all fieldsRead (SELECT) policyDirect
View only some fieldsNo row-level equivalent — a view or server function exposes the allowed columnsNeeds a decision
Auto-bind (edit from the page)UPDATE policy plus column-level grants for those fieldsOnly for rules that tie the row to the user
Creating and deleting thingsServer code (your workflows), not browser policiesAs in Bubble, where workflows create and delete
“Ignore privacy rules” in API workflowsServer code with the service role, which bypasses RLSKeep it on the server only

Two Bubble permissions have no one-to-one Postgres equivalent: Find this in searches (a row you may read is a row you may query) and View files attached to this (files live in Supabase Storage, which has its own policies).

03Where translations go wrong

  • Forgetting to switch RLS on. A Supabase table without RLS is readable by anyone with your public key. Every table needs it enabled, even a public one (with an explicit “anyone can read” policy).
  • Treating “Everyone else” as just another rule. If it’s OR-ed in like the others, users who match a stricter rule suddenly get the broader “everyone” access too.
  • Hiding fields with RLS. It can’t. A rule that shows a user only some fields of another user’s profile needs a view with those columns — otherwise the hidden columns are readable.
  • Letting users edit privileged fields. If a rule depends on “is admin” or a role, that column must not be editable by the user themselves, or they can promote themselves.
  • Conditions that can’t be expressed. Some Bubble conditions (multi-step lookups, for example) don’t translate to a simple policy. The safe default is to grant nothing and flag it, not to guess.

04What deBub does with your rules

deBub reads the privacy rules from your export and writes one read policy per table that reproduces Bubble’s additive logic, including the “Everyone else” fallback. Auto-binding rules become update policies limited to their fields, and the columns your rules depend on (roles, admin flags) are never editable by the user. Creating and deleting records runs through server code, as your workflows did.

Every rule appears as a comment next to its policy, so you can check the translation line by line. Where a rule can’t be expressed — a condition RLS can’t evaluate, or field-level visibility — deBub grants nothing for it, marks it in the code and lists it in your app’s report and security report.

Questions

Do Bubble privacy rules work in Supabase?
Not as such, but Postgres row-level security does the same job: each table returns only the rows a policy allows for the signed-in user. Most Bubble rules translate directly.
Can RLS hide individual fields like Bubble can?
No. Row-level security decides which rows a user sees, not which columns. Field-level rules need a view or a server function that returns only the allowed columns.
What happens to the “Everyone else” rule?
It becomes a branch of the read policy that applies only when none of the other rules match, which is exactly how Bubble evaluates it.
Do workflows still bypass privacy rules?
Server code that uses Supabase’s service role bypasses RLS, like an API workflow with “Ignore privacy rules”. Keep that code on the server and check permissions there.

Sources

  1. Bubble manual: Protecting data with privacy rules — checked October 16, 2026
  2. Supabase docs: Row Level Security — checked October 16, 2026

The deBub team

We build the Bubble → Next.js compiler behind deBub. Spotted something out of date? Write to hello@debub.io.

Mapping guide

Bubble to Next.js + Supabase: what maps to what

A concept-by-concept map from Bubble to Next.js and Supabase: pages and elements, workflows, data types, option sets, privacy rules → RLS, auth, files and plugins.

11 min read

Leave Bubble.
Keep building.

The scan is free and shows your exact price. No card needed until you choose to generate.

Start with a free scan