Every multi-tenant application makes the same promise: your data is yours, and no other customer can see it. The question worth asking any vendor is how that promise is kept — because there’s a big difference between “we filter by tenant in our code” and “the database refuses to return another tenant’s rows.”
WHERE tenant_id = ?The common approach is to add a tenant filter to every query. It works, right up until it doesn’t. All it takes is one endpoint where a developer forgets the clause, one raw query built for a report, one JOIN that widens the scope, one clever ORM call that skips the usual path. There’s no single place that guarantees isolation — it’s re-asserted by hand in hundreds of queries, and it only takes one miss to leak.
These bugs are quiet. Tests pass, because tests usually run as one tenant. The leak shows up when a real customer sees a document that isn’t theirs — the worst possible moment, and the worst possible way, to discover the boundary was never really there.
NDMS puts isolation in the database with Postgres row-level security (RLS). Every tenant-owned table carries a policy: a row is only visible when its tenantId matches the tenant of the current session. The application sets that tenant context at the start of each request, and from then on Postgres itself filters every read and write — SELECT, JOIN, report query, all of it.
Two properties make this strong:
RLS doesn’t replace application-level checks — it backs them up. Requests still resolve the tenant from the authenticated session (never from client input), and roles still gate what each user can do. RLS is the layer underneath that holds even when something above it slips. On top, per-tenant KMS keys separate data cryptographically on shared storage.
The point isn’t that any one of these is unbeatable. It’s that isolation shouldn’t rest on every developer remembering a filter forever. It should be a property of the system.
Next time a multi-tenant vendor says “your data is isolated,” ask the follow-up: isolated by what? If the answer is “our code filters by account,” you’re trusting their discipline on every query they’ll ever write. If the answer is “the database enforces it and our app can’t bypass it,” the boundary is real — and it stays real as the codebase grows.
Ready to see it? NDMS runs the whole document lifecycle — capture, search, e-signature, retention and disposal — with hard tenant isolation and a full audit trail. Start free →