Blog ·

What "multi-tenant by design" actually requires

Adding a tenant_id column isn't multi-tenancy. Here's what real multi-tenant infrastructure for MSPs actually requires, and the one-question test that tells you whether a tool has it.

"We added a tenant_id column" isn't multi-tenancy.

The phrase "multi-tenant" shows up in every MSP-targeting tool's marketing. Most of the time, what it means is: there's a tenant_id field on the rows in the database, and the app filters by it. That's table stakes for any SaaS, not multi-tenancy in the sense an MSP needs.

For an MSP running 30+ client tenants in production, multi-tenant means something specific. Here's what it actually requires.

Tenant boundaries enforced at the data layer

Filtering by tenant_id in application code is fine until someone forgets the filter. A single query in a single new endpoint that omits the WHERE clause leaks data across tenants. The next discovery is a panicked call from a client who saw another client's tickets.

Real tenant isolation enforces the boundary at the data layer: row-level security in Postgres, per-tenant schemas, per-tenant databases. The app can't leak across tenants because the database won't return cross-tenant rows even if asked.

Question to ask: "What protects against a query that forgets the tenant filter?"

Scoped credentials per tenant

Each client tenant has its own API tokens, OAuth grants, M365 connections, etc. The tool stores those credentials in a way that an automation acting on Tenant A cannot reach Tenant B's credentials even within the same process.

The wrong pattern: one shared admin credential that's "scoped via app logic." When that logic has a bug, you get cross-tenant blast radius.

The right pattern: per-tenant credential vaults, with the tool's identity for Tenant A having no read access to Tenant B's vault.

Question to ask: "If your code has a bug that accesses the wrong tenant's credentials, what stops it?"

Per-tenant configuration

Every tenant has its own:

  • Ticket statuses and types
  • Custom field schemas
  • Escalation rules
  • Naming conventions (security groups, distribution lists, license assignments)
  • Business hours, holidays, on-call rotations

Real multi-tenancy means the tool reads each tenant's actual config at runtime. It doesn't hardcode defaults and hope. If Tenant A uses "Awaiting Vendor" as a status and Tenant B uses "Waiting on Supplier," the tool handles both without code changes.

Question to ask: "How do you handle a tenant with a custom field schema that doesn't match the demo tenant?"

Isolated failure modes

When something breaks for Tenant A, Tenants B–Z keep working. This sounds obvious. It's not how shared-everything SaaS usually works. The wrong pattern: one bad webhook call from Tenant A's tenant fills up a shared queue and stops processing for everyone.

The right pattern: per-tenant queues, per-tenant rate limits, per-tenant circuit breakers. The blast radius of any single tenant's problem is that single tenant.

Question to ask: "What happens when one of my tenants generates a flood of events. Do the others get throttled?"

Audit trails per tenant

Every action the tool takes is logged with the tenant it was acting on behalf of. Retention is per-tenant (so compliance requirements differ per client without compromise). Export is per-tenant.

Question to ask: "Show me the audit trail for an action your tool took on Tenant X six months ago."

The single-question test

If you only have time to ask one question to test a tool's multi-tenancy claim:

"Can I onboard a new tenant tomorrow without you doing any code changes on your side?"

If the answer is "yes, here's the self-service onboarding flow," it's multi-tenant.

If the answer involves their team setting something up (even a config flag), it's a single-tenant tool with multi-tenant aspirations.

For an MSP picking up new clients, that distinction shows up in week three.


What's the worst "multi-tenant" tool you've onboarded that wasn't actually multi-tenant?

← All posts