Home / Knowledge hub / Row-level security
Knowledge hub
Row-level security
Database rules that limit which rows each account can read or change.
What it means
Row-level security, often shortened to RLS, is a database feature that filters rows before your query sees them. You define a policy, such as "a row is visible only if its tenant matches the current account", and the database applies it to every query automatically.
PostgreSQL, for example, lets you enable it per table and write policies that decide which rows a role may select, insert, update or delete. The rule moves from application code, where it can be forgotten, to the data itself, so that it applies however the query was written.
Why it matters
The value is a safety net. A developer who forgets a filter in one query no longer exposes every customer's rows, because the database refuses to return them. For multi-tenant products that single change can remove a whole class of leaks.
It is not a complete answer, and it should not be sold internally as one. A policy that is wrong, or bypassed by how the application connects, gives false comfort. Auditors like it because the control is visible in one place, but it still has to be tested like any other control.
How it shows up
In practice the application sets the current account or tenant for each connection or transaction, and policies read that setting. The common mistakes are connecting as a database owner or superuser, which can bypass policies, forgetting to enable it on a new table, and background jobs that run without any tenant set.
Policies also need their own tests. Check the "write" side, not only reads, and check views, functions and joins. Then look at what the application does around it: object-level authorisation in the API still matters for rules the database cannot express.
Questions people ask
Row-level security, answered
Does row-level security replace checks in the application?
No. It is a second layer. The application still needs to decide what an account may do, and some rules, such as business approvals, do not fit in a table policy.
Think of it as a backstop for the common mistake of a missing filter.
Which databases support it?
PostgreSQL has had it for years, and Microsoft SQL Server and Oracle have comparable features under other names. Support, syntax and limits differ between products.
Check your database's own documentation for how policies are defined and what can bypass them.
Can row-level security be bypassed?
Yes, in several ways. Table owners and superusers can bypass policies in PostgreSQL unless forced otherwise, and a wrongly written policy can allow more than intended.
Connecting the app as a powerful database role is the most common way it is defeated by accident.
Does it slow queries down?
Policies add conditions to queries, so poorly written ones can slow them, especially if they use subqueries or unindexed columns.
Index the columns your policies use, and measure with real data volumes.
How do we test that it works?
Connect as the application's role with the tenant set to one customer, then try to read, update and delete rows belonging to another. Try through the API too.
Test new tables and migrations, because that is where policies get forgotten.
Sources
Where this comes from
Related
Terms that sit next to this one
Multi-tenancy
One running application serving many customers whose data must stay apart.
Tenant isolation
What keeps one customer's data unreachable from another's session.
Ownership check
Confirming that the record being requested belongs to the account asking for it.
Least privilege
Giving every person and service the minimum access the job requires.
Server-side authorisation
Enforcing permissions on the server, because hiding a button in the page protects nothing.
Is the safety net holding?
Database rules help only if the application connects and sets context correctly. We test what a signed-in account can reach that it should not, and show the exact request. In white-box mode we point to the code. Book a pilot on one app.
Or start with a $199 pilot on one application: thirty days, success criteria agreed before day one, credited against the annual if you convert.