Skip to main content
Row-level security (RLS) is a per-member filter applied on top of a database or entity the member already has access to. It answers the question “of the rows in this table, which ones is this person allowed to see?”

When to use it

Resource permissions decide whether a member can read a dataset at all. RLS decides which rows inside it they see. Typical reasons:
  • A salesperson should see only their own accounts in customers.
  • A regional manager should see only invoices for their region.
  • Each site’s staff should see only their site’s rows—one policy, filtered per person.
If a member shouldn’t see the table at all, revoke the resource grant—don’t try to enforce that through RLS. With no policies, access is unrestricted: everyone who can read the dataset sees every row. Each policy you add limits which rows its audience sees.

What a policy says

A row policy reads as a sentence:
<audience> can only see rows where <column> <operator> <value>
It has four parts.

Audience — who the policy applies to

Column and operator

The policy filters one column. Available operators:

Value source — static or dynamic

This is the part that makes one policy serve a whole team: A user-attribute policy uses equality operators only (= or IN). And it fails closed: a member with no value for that attribute sees no rows. This is deliberate—a blank attribute must never mean “see everything.”

Combining policies

A member can be hit by several policies. Two rules decide the result. Different columns AND together. A policy on site and a policy on status both apply—a row must pass both to be visible. Same column: the most specific audience wins. If more than one policy targets the same column, precedence is user > group > everyone. The most specific tier applies and the others are skipped for that column. Example: “everyone sees only their own site” plus “the Directors group sees sites A–D” means a director sees A–D (the group tier wins over everyone), while everyone else sees just their own.

Where filters are applied

RLS is enforced server-side, before data ever reaches the member:
  • Pipeline and dashboard reads — applied as a WHERE wrapper or an in-memory filter before the table is served.
  • App queries — the app’s query endpoint reuses the same resolution.
  • Natural-language queries — the ontology query path applies RLS to the generated SQL.
  • Chat tools — data-returning assistant tools resolve the same filters, so the AI can’t surface rows you couldn’t see.
  • Action writes — when a viewer writes a row through an app action, the platform checks the new row against the member’s filters and rejects writes that would land in a row they couldn’t read.

Fail-closed on writes

For reads, a row missing an RLS-filtered column is skipped (the platform can’t evaluate the filter, so it conservatively excludes the row). For writes, a payload missing an RLS-constrained column is rejected—otherwise a viewer could dodge their policy by omitting the column.

Who bypasses RLS

  • Owners are never subject to RLS.
  • A member with effective Admin on the dataset (direct or inherited) is not filtered—they manage it, so they see all of it.
  • Everyone else—admins and viewers without Admin on that dataset—is filtered.

Configure a policy

From the dataset or entity’s Access panel, open Row-Level Security and Add policy:
  1. Pick the column to filter.
  2. Choose the value source—specific values, or a user attribute.
  3. Pick the operator and enter the values (or select the attribute).
  4. Choose the audience—everyone, a group, or a member.
  5. Save. The policy takes effect on the next query.
Test by impersonating the member or using a viewer account—the filtered table should show only the matching rows.