Support

Need help?

Most answers are already written down. For everything else, Oneop does not publish a response time — there is no SLA instrument behind one — so the fastest thing you can do is send a complete first message.

Search the help centreEmail support@oneop.ioOpen your workspace

Worth including

  • The email you log in with
  • The URL of the screen it happened on
  • What you expected, and what happened instead

Goes somewhere else

Security

Multi-tenant SaaS isolation: what to ask your vendor

By The Oneop team8 min read

TL;DR

Multi-tenant isolation is only as strong as the layer that enforces it. Ask where the tenant identifier is applied, whether any query path can omit it, how backups and restores are scoped, what limits one tenant's load, and how an incident affecting one tenant is contained. Vague answers to those five are the finding.

Security questionnaires ask whether a vendor is multi-tenant. Almost every SaaS product is, so the answer is yes and the question was wasted. The question that produces information is where the tenant boundary is enforced, because that single design decision determines whether a cross-tenant leak requires a deliberate attack or a distracted afternoon.

What follows is a question list you can send to a vendor, with the reason each question matters. The reasons are the useful part: they tell you what a bad answer costs you.

Question 1: where is the tenant identifier applied?

There are three honest answers, and they are not equally strong.

In application code, per query. Every query is written with a tenant predicate by a developer who remembered. This works until someone does not remember. It is the most common architecture in SaaS and the weakest, because correctness depends on unbounded future discipline.

In the data layer. Scoping is applied by the layer that builds queries, not by the developer writing them, so a query that omits the tenant cannot be constructed on that path. This is strong when it is genuinely inescapable and theatre when there is a raw-query escape hatch that half the codebase uses.

In the database engine. Postgres row-level security policies enforce scoping below the application. Strongest, and rarer, because it requires session-variable discipline in connection pooling.

Ask which one, then ask the follow-up that matters: what percentage of endpoints bypass it, and what is on the other side of the bypass?

Question 2: what does the schema look like, and what is not tenant-scoped?

TopologyLeak requiresReal operational cost
Shared tables, tenant columnOne missing predicate on one query pathLowest; one migration set, one backup
Schema per tenantA connection routed to the wrong schemaMigration fan-out across every schema
Database per tenantConnection-string or routing errorHighest; per-tenant patching, backup, monitoring

A vendor who answers “shared tables” is not giving you a bad answer. A vendor who cannot tell you which tables are not tenant-scoped is. Every real system has some: reference data, platform configuration, the tenant registry itself. The ones worth worrying about are the tables that hold customer business data and somehow escaped the pattern.

Oneop’s security page publishes this as a count rather than a posture: 275 of 329 tables carry a tenant_id column, and the remaining 54 are itemised. 28 belong to the internal operator console, which is a separate application that ships disabled. 18 are child records inheriting the boundary through a foreign key to a tenant-scoped parent. 4 hold global reference data such as tax jurisdictions and VAT rates. 3 are a shared directory of publicly published company information. One is the tenant registry. That enumeration is the answer you want from any vendor, whatever their numbers turn out to be.

Question 3: can a caller choose their own tenant?

Registration and invitation endpoints are the interesting attack surface, because they accept input before a session exists. If a signup request body containing a tenantId is honoured, an attacker joins your workspace rather than creating their own. The same applies to role: if the request body can set role: admin, the boundary was never the problem.

The correct behaviour is that public registration always provisions a new tenant, a caller-supplied tenant identifier is rejected outright rather than ignored, and the initial role is hardcoded rather than read from the request.

A related question worth asking: do update endpoints run a mass-assignment guard? If a PATCH copies arbitrary request fields onto a record, then fields you never exposed in the UI, including ownership fields, are writable by anyone who can guess a column name.

Question 4: the failure case to ask about directly

Ask what happened the last time a query shipped without a tenant predicate, and what stopped it.

Here is the shape of the incident. A developer adds an export endpoint for a new report. The list endpoint beside it uses a scoped query builder; the export uses a raw SQL string for performance, because the report joins four tables and the builder generated a slow plan. The raw query filters by date range and status, which was the whole feature request, and nobody notices that the tenant predicate was in the builder rather than in the requirement.

The endpoint passes review because the reviewer checks the SQL for correctness against the feature, not against an invariant nobody wrote down. It passes tests because the test fixture has one tenant. It ships. Three months later a customer opens a CSV containing another customer’s contact list, and the disclosure obligation is triggered by an export rather than a screen, which means the data has already left both buildings.

Every element of that story is ordinary. That is the argument for enforcement below the developer: the mistake is not exotic, so the control cannot rely on the mistake being rare.

Reporting systems deserve the same question, because a report builder is a query builder with a user interface on it. In Oneop’s reporting engine, the workspace filter is not part of the report configuration at all; the engine builds it from the dataset definition, applies it to the base table on every query, and applies it again to each joined table rather than trusting the relationship to have carried it. A report definition names dimension, measure and filter keys from a server-owned catalogue, so there is no configuration that can widen or remove the predicate.

Question 5: how are backups and restores scoped?

This is the question that separates vendors who have practised recovery from vendors who have configured it.

Ask: can you restore one tenant to a point in time without rolling back every other tenant? If the answer is no, then recovery from your own accidental deletion competes with everyone else’s uptime, and the practical resolution is that it will not happen.

Ask where backups live, how they are encrypted, and whether the key is held somewhere the compromised server cannot reach. A backup encrypted with a key stored beside it protects against disk failure and not against an intruder. Ask about every copy, including the infrastructure-level ones: host snapshots taken by the hosting provider are a second copy of your data under a different retention policy, and a vendor who has not mentioned them has not finished the inventory.

Question 6: what limits one tenant’s consumption?

Data isolation and performance isolation are different properties. One tenant running an unbounded export, a runaway automation loop or an integration retrying in a tight cycle can degrade everyone on shared infrastructure.

The answers that indicate thought are numeric: per-tenant rate limits on public endpoints, a row ceiling on report execution with truncation reported rather than hidden, a cap on concurrent jobs. Oneop’s reporting engine caps at 5,000 rows per run and marks a capped result as capped, which is a limit that is also a correctness property.

Question 7: how is staff access constrained?

Somebody at the vendor can reach the database. Pretending otherwise is the unreliable answer. The useful questions are whether staff access to customer accounts runs through a separate application with its own login and mandatory two-factor, whether sessions are time-boxed, whether they can be revoked mid-session, and which actions are hard-blocked.

Then ask the one people forget: can the access log be modified or deleted by the people it records? An audit log with an update route is a document, not a record.

Question 8: how is an incident affecting one tenant contained?

Containment is mostly about blast radius decided in advance. Shared session-signing secrets across different classes of user are a good probe, because they are a common shortcut: if the staff application, an admin console and a customer-facing portal sign sessions with the same secret, a cookie minted in one realm can be replayed in another.

Ask whether separation is enforced at boot or by deployment convention. Oneop runs three session principals with three cookie names and three signing secrets, and production start throws unless all three are distinct, which turns a configuration error into a failed deploy rather than a latent vulnerability.

How to read the answers

Precision is the signal. A vendor who answers with counts, enforcement points and named failure behaviours is describing a system they have examined. A vendor who answers with adjectives and a certificate number has told you about their audit, which is a different thing from their architecture. For the equivalent question set applied to AI capability claims, see what is an AI-first customer platform; for why placement inside the boundary changes what software can be trusted to do, why your AI agent should live inside your system of record covers the argument. Pair this list with how Oneop governs AI if agents will touch the same data.

Frequently asked questions

Is a separate database per tenant more secure than row-level isolation?

It fails differently rather than strictly better. Separate databases make cross-tenant leakage require a connection-routing mistake instead of a missing predicate, which is a smaller target. They also multiply the operational surface: hundreds of schemas to migrate, patch and back up, where a missed migration becomes its own class of incident. Enforced row-level scoping in one database is defensible; unenforced scoping in any topology is not.

What actually happens when a WHERE clause is missing?

One customer sees another customer's rows, and usually nobody notices immediately. The severity depends on the endpoint: a list view leaks records to a screen, an export leaks them to a file that leaves the building, and a write path can modify or delete data belonging to a tenant who never made a request. This is why the enforcement point matters more than the review process.

Should I ask a vendor for their SOC 2 report?

Ask, but do not stop there. A certification tells you an auditor tested a described control set in a window; it does not tell you where the tenant identifier is applied or what a restore does. Pair the certificate question with mechanism questions, because a vendor who can answer the mechanism questions precisely is demonstrating something the certificate cannot.

What is a noisy neighbour problem in multi-tenant SaaS?

A noisy neighbour is one tenant consuming shared capacity to the point that other tenants degrade: an unbounded export, a runaway automation loop, an integration retrying in a tight cycle. Isolation of data does not imply isolation of performance, so ask about per-tenant rate limits and query ceilings separately from ask about data separation.

How should a vendor handle restoring one tenant's data?

A vendor should be able to describe restoring a single tenant without rolling every other tenant back in time. If the only recovery mechanism is restoring the whole database to a point in time, then recovering your accidental deletion means discarding everyone else's last hour, which means in practice they will not do it.

Can vendor staff read my data?

Almost always yes, technically, because someone has to operate the database. The meaningful questions are whether staff access runs through a separate, logged path, whether it is time-boxed and revocable, which actions it is blocked from taking, and whether the access log can be deleted by the people it records.

Written by

The Oneop team

Writing from the team that builds Oneop — an AI customer platform with web chat and email on top of a real CRM, help desk, ledger and warehouse.

Related reading

Start on the free plan and see the real thing

No credit card. Free plan, 2 seats.

Free forever · 2 seats · No credit card