
The workload
Software storing more than one customer's data in a shared table has to keep customer A from ever seeing customer B's rows, no matter how a bug in the application code queries the table. PostgreSQL's own documentation on row security policies describes a database-level control for exactly this: row-level security (RLS), enabled per table, plus one or more policies created with CREATE POLICY. Turning it on is a schema change, not a subscription: enable RLS, then write a policy expression, typically comparing a tenant-identifier column to the connected role. That is developer and database-administrator time, not a vendor bill, though several managed Postgres platforms build multi-tenant offerings around this mechanism.
What the documents show
PostgreSQL's documentation states, verified, that once row security is enabled on a table, 'if no policy exists for the table, a default-deny policy is used, meaning that no rows are visible or can be modified' — a stricter starting point than an unenabled table. The CREATE POLICY reference states, verified, that a policy's USING expression governs which existing rows a role can see, its separate WITH CHECK expression governs which new or modified rows it can write, and a policy can be scoped to SELECT, INSERT, UPDATE, DELETE or ALL. The row-security page also states, verified, a limit a checklist alone would not surface: 'superusers and roles with the BYPASSRLS attribute always bypass the row security system,' and table owners normally bypass it too, unless the table is explicitly altered to force row-level security on its own owner. A design that assumes RLS applies uniformly to every role is wrong unless that exception is accounted for.
The operating cost
RLS carries no separate fee; it is part of the database engine. The cost is engineering time to write correct policy expressions and, as the documentation itself states, to test them: 'as with any security settings, it's important to test and ensure that the system is behaving as expected.' The documents do not quantify that effort in hours, and it depends on schema complexity, so no figure is given here.
The stop condition
The documentation does not name a point at which RLS testing is complete. This is an editorial stop condition: coverage is reasonable once every table holding tenant-scoped data has RLS enabled, a policy exists for each operation the application performs, the bypass roles — superuser, BYPASSRLS, table owner — are confirmed not to be roles the application connects as, and a cross-tenant query has actually been attempted and denied in a test environment, not assumed to fail from reading the policy text.
- Which roles does the application actually connect as, and do any of them bypass row security?
- Does a policy exist for every command type the application issues against the table?
- Has a cross-tenant read been attempted and confirmed to fail, not just assumed to fail?
PostgreSQL's own documentation describes row-level security as a database-enforced default of denial, a stronger starting position than trusting application code alone, but the same pages are explicit that untested policies and unaccounted-for bypass roles remain the application owner's problem, not the database's.
Sources & reading trail
States the default-deny behavior and the superuser/BYPASSRLS/owner bypass rules.
Source published: Not established · Retrieved: 16 September 2026
Defines the USING and WITH CHECK clauses and the commands a policy can cover.
Source published: Not established · Retrieved: 16 September 2026
Vendor documentation, regulator records and founder-published documents establish the entry; the workload reading and the stop condition are Solo Product Office editorial analysis. This retrospective draft does not imply the site published on the event date.