RBAC & Row-Level Security
What it is
Section titled “What it is”AetheriusDB ships a complete authorization stack: named roles with granted
privileges, and fine-grained row-level policies that filter which rows each
user can see. Together they let you run a single shared cluster as a strict
multi-tenant service, where every tenant behaves as if they had a private
database — using the standard CREATE ROLE, GRANT, and CREATE POLICY SQL
that operators already know.
Row-level security predicates are compiled into the query plan, so applying tenant isolation across a large table does not require a separate filtering pass on top of every query. The same SQL run by two different users returns two disjoint result sets, with no application changes.
Why it matters
Section titled “Why it matters”- Standard SQL surface —
CREATE ROLE,GRANT, andCREATE POLICYbehave the way Postgres operators expect. - Per-tenant isolation by default — a row-level policy keyed on a session variable keeps tenants from reading each other’s rows, even when they run identical queries.
- Column and row controls compose — combine
GRANT SELECT (col1, col2)with a row policy to express “this role can read a subset of columns for a subset of rows” without hand-writing a view.
How you use it
Section titled “How you use it”The example below creates a role, grants table access, and defines a row-level policy so every tenant only sees their own orders.
-- 1. Create a role and grant table-level privileges.CREATE ROLE tenant_reader;GRANT SELECT ON orders TO tenant_reader;
-- 2. Attach a row-level policy that filters by the session's tenant.ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON orders FOR SELECT TO tenant_reader USING (tenant_id = current_setting('app.tenant'));
-- 3. Bind a user to the role and set the tenant for this session.GRANT tenant_reader TO alice;SET app.tenant = 'acme';
-- 4. Same SQL, two tenants, two filtered result sets — no app changes.SELECT id, total FROM orders WHERE total > 100;Alice sees only orders where tenant_id = 'acme'. A user bound to a different
tenant runs the same query and gets a disjoint result set — the row-level policy
is applied automatically, not as something the application has to remember to
add.
Key concepts
Section titled “Key concepts”| Term | Meaning |
|---|---|
| Role | A named bundle of privileges. Users inherit privileges by membership. |
| Policy | A predicate attached to a table that filters rows per user, per operation. |
| Session variable | A per-session value (for example a tenant id, via SET / current_setting) that policies can reference at runtime. |
| Column privilege | A GRANT that restricts a role to specific columns of a table. |