Row-level security (RLS) is a database feature that controls which individual rows of a table each user is allowed to read or modify, with the rule enforced by the database engine rather than your application. You write a policy once, for example ‘a user can only see rows where the tenant ID matches their own’, and every query is filtered automatically against it.

Imagine a shared filing cabinet where every folder is tagged with a customer name. RLS is like a clerk who, before handing you any folder, checks your badge and only gives you the ones that belong to you. It does not matter which door you came through or which form you filled in; the clerk applies the same rule every time.

This is powerful because it moves the guardrail closer to the data. Even if a developer forgets a check in the app, or a reporting tool connects directly, the database still refuses to hand over rows the user should not see. RLS works hand in hand with authentication to know who is asking and with RBAC to decide what they can do.

A practical warning: RLS is only as good as the identity the database trusts. Postgres, for instance, reads a session variable that your app sets per request, so if a connection is reused across users without resetting that value, one person can inherit another’s view. Pooled connections are the classic place this goes wrong, which is why the policy and the way you set the current user have to be designed together, not bolted on later.

At TopDevs we lean on row-level security in multi-tenant apps so one customer can never accidentally see another’s data, even when something else in the stack goes wrong.