How would you make it structurally impossible for a developer to add an endpoint that returns another tenant's data?
Show the full answer Hide the answer
What is being tested
Whether you reach for structural enforcement rather than for process, and whether you know the mechanisms available at each layer.
The layered answer, strongest first
1. Physical isolation per tenant. Separate databases, or separate cells per tenant group. Cross-tenant access is impossible because there is no path — the data is not in the same place. This is the strongest guarantee available and the easiest to explain to an auditor, and it costs more infrastructure and makes cross-tenant analytics genuinely hard.
For enterprise products with residency or isolation requirements this is frequently the right answer, and it doubles as a commercial product tier.
2. Row-level security in the database. A session variable carries the tenant; the database enforces that every query is filtered. A query without tenant scoping returns nothing rather than everything — which is the inversion that matters. The application cannot bypass it, including from an admin tool or a migration script.
3. A data access layer that requires tenant context. Repositories take a tenant-scoped context object; there is no method that returns unscoped data. Bypassing it means importing the raw database client, which a build-time check can forbid.
4. Automated negative tests generated from the route table. Every endpoint automatically gets a test asserting that tenant B's token receives a denial for tenant A's object. A new endpoint without one fails the build. This catches the absence, which review does not.
5. Runtime detection. Log and alert whenever a response contains an identifier belonging to a different tenant than the caller. A last line of defence that catches what everything above missed.
The layers ranked by what they cost
| Mechanism | Guarantee | Cost |
|---|---|---|
| Separate databases or cells | Strongest | Infrastructure, hard cross-tenant analytics |
| Row-level security | Very strong | Some engine coupling, care with connection pooling |
| Scoped data access layer | Strong if enforced | Requires a lint or build check to prevent bypass |
| Generated negative tests | Catches absences | Build time, test maintenance |
| Runtime detection | Detective only | Alerting noise if imprecise |
Most systems should use several. The combination that gives most of the value for least cost is usually row-level security plus generated negative tests.
The trap in row-level security
Connection pooling. If the tenant is set as a session variable and connections are reused across requests, a connection can carry the previous request's tenant. The setting must be applied per transaction, or the mechanism silently fails in exactly the way it was meant to prevent.
What a strong answer adds
That the same question applies to asynchronous paths — background jobs, exports, webhooks, analytics pipelines and admin tools frequently bypass the scoped layer entirely. Those are where cross-tenant leaks actually occur, because the API path is the one everybody remembers to protect.