The hard part of multi-tenant SaaS architecture is not the shared server. It is making sure no query, cached value, queued job or socket message can reach the wrong tenant, even on the day a developer forgets. The proof behind this guide is 3DLogistiX, an Australian warehouse management SaaS where Sigi Technologies supplied embedded engineering capacity on a staff-augmentation basis. Commercial scope for a platform of this shape sits on Sigi’s SaaS development service.
What is multi-tenant SaaS architecture?
A tenant is one customer organization and its users, sharing an application instance with other customer organizations. Multi-tenant SaaS architecture is the set of decisions that let one codebase and one running deployment serve those tenants while each sees only its own data. The AWS Well-Architected SaaS Lens calls tenant isolation a foundational topic for every SaaS provider and warns that a tenant crossing into another tenant’s resources in any form could be an unrecoverable event for the business. Microsoft’s Azure guidance frames the choice as a spectrum from fully isolated to fully shared rather than a switch.
- Multi-tenancy is a commercial decision as much as a technical one: shared infrastructure lowers cost per tenant, dedicated infrastructure raises isolation and predictability at a higher cost per customer.
- The three standard SaaS tenancy models are silo (dedicated resources per tenant), pool (shared resources) and bridge (a mix, decided per service), as defined in the AWS SaaS Lens.
- Isolation must be enforced in the service layer before business logic runs; a tenant filter that developers remember to add is a convention, not a boundary.
- A tenant identifier belongs on every stored document, every cache key, every queue message and every realtime channel, not only on database rows.
- Broken access control was found in 100% of the applications tested for the OWASP Top 10:2025, so cross-tenant tests belong in the build pipeline, not a launch checklist.
Single-tenant vs multi-tenant: which SaaS tenancy model should you choose?
Single-tenant vs multi-tenant is rarely an all-or-nothing choice. AWS describes three SaaS tenancy models, and most real products mix them.
- Silo: each tenant gets dedicated resources, from a separate database up to a full stack, still managed through shared identity, onboarding and operations. AWS lists compliance support, no noisy neighbor concerns and a limited blast radius as benefits, and cost, agility and onboarding automation as the costs of the silo model.
- Pool: tenants share compute, storage and messaging. Resources scale with actual load and all tenants are managed through one experience, but AWS warns that sharing increases the chance of cross-tenant access and requires special diligence about isolation.
- Bridge: some services siloed, others pooled. A service holding regulated data or carrying heavy load can be siloed while the rest stays pooled, which AWS calls the bridge model.
Microsoft’s tenancy models guidance adds two hybrids: vertically partitioned, where most tenants share and a few get dedicated stacks, and horizontally partitioned, where the application tier is shared and each tenant gets its own database. 3DLogistiX runs as a pool: each customer’s facilities, users and roles are provisioned through the admin panel, not a new deployment.
Shared database vs database per tenant
The most argued sub-decision is shared database vs database per tenant. Microsoft’s guidance on multitenant storage and data lists three patterns: a shared multitenant database (highest density and lowest cost, but hard scale limits and awkward per-tenant restore), sharding (several databases, each holding one or more tenants), and a database per tenant (isolation and some customization at higher cost, workable only with automated provisioning). It also names the antipatterns: a table per tenant, per-tenant columns, and manual schema changes.
The rule of thumb from that guidance is to keep the architecture as simple as the requirements allow and to move a tenant to its own database only when it needs its own encryption keys, backup policy or data residency. On 3DLogistiX, MongoDB holds per-tenant configuration, facility layouts and rack hierarchies as nested documents in shared collections, with the tenant identifier on every document. A per-tenant database would have added operational cost without changing the isolation rule.
Why should tenant isolation be a service-layer rule, not a convention?
Tenant isolation is the guarantee that one tenant cannot read, change or affect another tenant’s resources. In a pooled model the usual network and IAM boundaries do not separate tenants, so the guarantee has to live in code paths that every request passes through. AWS’s isolation whitepaper describes the pattern that connects identity to isolation: authentication returns a tenant context, that context flows through every interaction, and downstream services use it to scope access to resources.
The failure mode is a query filter. If every repository method takes a tenant identifier as an argument and every developer is expected to pass it, the first forgotten argument becomes a cross-tenant read. OWASP’s advice on broken access control says the same about ownership: implement access control once and reuse it everywhere, deny by default, and enforce record ownership rather than trusting the caller to filter.
In practice: resolve the tenant once, at the edge, from the authenticated session, never from a client-supplied parameter; attach it to a request context the data layer reads for itself; and make that layer refuse to run without a tenant in scope.
How do you keep data, cache, queue and realtime channels tenant-scoped?
Data: the tenant identifier on every record
In a shared database, every table or collection holding tenant data carries a tenant column, indexed with the fields queries filter on. In PostgreSQL, row-level security can enforce this inside the database: once enabled on a table, all access must be permitted by a policy, and a table with no policies falls back to default-deny. Two caveats in the same documentation matter for SaaS: table owners and superusers bypass the policies unless FORCE ROW LEVEL SECURITY is set, so an application connecting as the table owner gets no protection, and referential integrity checks always bypass row security, so a unique constraint or foreign key can reveal that another tenant’s row exists. Microsoft’s data guidance adds that the feature needs tenant identity propagated with every query and that many teams skip it for that reason. Treat it as a second layer beneath the service-layer check, not a replacement.
Cache: tenant-aware caching with prefixed keys
A cache key without a tenant prefix is a cross-tenant read waiting for two tenants to share an entity identifier. Build every key as tenant, then entity, then identifier, and make invalidation able to clear one tenant’s keys without touching another’s. On 3DLogistiX, Redis holds the current-quantity and task-state data the live views poll constantly, and each of those keys carries the tenant identifier.
Queues and events: tenant context travels with the message
When work leaves the request and enters a queue, the request context is gone. The tenant identifier has to travel in the message body or attributes so the consumer can re-establish scope before touching data. On 3DLogistiX, SQS and SNS carry stock-movement events between the inventory, orders, tasks, visualization and replenishment services; a handset scan becomes an event that each consumer processes inside the tenant it belongs to.
Realtime: channels scoped to a tenant
WebSocket rooms, pub/sub topics and push subscriptions need the same prefix, and a subscription must be authorized against the tenant in the session, not a channel name the client sends. On 3DLogistiX, WebSockets push stock changes to browsers and handsets over tenant-scoped channels, so a movement in one company’s warehouse never reaches another company’s 3D view.
How do you onboard a new tenant onto shared infrastructure?
Tenant onboarding is the process that provisions and configures everything a new tenant needs. The AWS SaaS Lens describes it as the orchestration of a number of components, started either by the tenant in self-service or by the provider. In a pool model no infrastructure is created, but the steps still need to be one automated, idempotent job.
- Create the tenant record and its identifier, then the first admin user bound to that tenant in the identity system, so tenant context is issued on login.
- Apply the tenant’s plan, limits, feature flags and defaults. Microsoft recommends feature flags and per-tenant configuration over forking code or infrastructure for one customer.
- Seed tenant-scoped assets. On 3DLogistiX these are facilities, layouts and 3D models, users and roles, provisioned from the admin panel.
- Connect billing. 3DLogistiX takes subscriptions through Stripe on three published tiers, so the tenant record carries its plan from day one.
- Smoke test as the new tenant, then as a different tenant, and confirm the second sees nothing of the first.
How do you stop noisy neighbors in a multi-tenant system?
The noisy neighbor problem is one tenant’s activity degrading another tenant’s performance because they share resources. Microsoft’s antipattern guidance notes that it can happen even when no single tenant is large, because many tenants’ peaks can coincide. The research literature treats performance isolation formally: Krebs, Momm and Kounev proposed three metrics for quantifying it in a SaaS scenario where tenants share one application instance, and Walraven and colleagues proposed middleware that enforces per-tenant service-level agreements with a tenant-aware profiler and scheduler. The controls, in the order to add them:
- Per-tenant telemetry first. Tag every request, query, queue message and socket event with the tenant identifier; without this you cannot tell a heavy tenant from a capacity problem.
- Rate limits and quotas at the API edge, per tenant and per plan, published so customers’ clients handle throttling.
- Bounded operations: cap record counts and query time, and move exports, bulk imports and reports to asynchronous jobs in their own queue.
- Fair scheduling on shared workers, so one tenant’s backlog cannot starve the others.
- Tier-based isolation last: move the heaviest tenants to their own database or stamp, the bridge model, rather than siloing everyone.
3DLogistiX handles its burstiest path at the edge: API Gateway and Lambda absorb spiky integration and webhook traffic, so one tenant’s burst scales serverless capacity instead of competing with the persistent services holding every tenant’s WebSocket connections.
How do you test a multi-tenant system for tenant leakage?
Multi-tenant security fails quietly. Broken access control is ranked first in the OWASP Top 10:2025, where 100% of the applications tested showed some form of it, across 40 mapped weaknesses and more than 1.8 million recorded occurrences. The classic instance is an insecure direct object reference: viewing or editing someone else’s record by supplying its identifier, which in SaaS means another tenant’s record. OWASP’s IDOR prevention guidance is to verify permission on every access attempt and to scope lookups to the caller’s own resources rather than searching all records and filtering afterward. Microsoft’s tenancy guidance adds that whichever model you choose, you should test that one tenant’s data never leaks to another. A usable test plan:
- Two-tenant fixtures in every integration suite, with overlapping entity identifiers, so a missing scope shows up as a failure rather than an empty result.
- Identifier-swap tests for every endpoint: authenticate as tenant A, request tenant B’s identifiers, and expect 404 or 403, never 200.
- Cache, queue and realtime tests: warm a cache as tenant A and read as tenant B; publish an event for tenant A and assert tenant B’s consumer ignores it; subscribe as tenant B to tenant A’s channel and assert the server refuses.
- Database-role tests when row policies are in use: confirm the application role is not the table owner.
- Log and alert on access control failures, as OWASP recommends, so a scan across tenant identifiers is visible.
On 3DLogistiX, Playwright end-to-end tests cover web flows such as receiving, pick-and-pack and layout editing, GitHub Actions runs the suites on every merge, and the WebSocket synchronization between handsets and browsers is exercised in the automated suite rather than by hand. Infrastructure changes go through CDK and are reviewed like any pull request.
When is single-tenant the right choice?
Single-tenant is right when the isolation requirement is contractual or regulatory, when the number of customers is small, or when one tenant’s load justifies dedicated capacity. Microsoft’s guidance is direct: with only a few customers, resources dedicated to each may be appropriate, and high isolation requirements can justify the cost. AWS allows the same for the silo model, provided identity, onboarding, metering and operations stay shared; without those it is managed hosting, not SaaS.
The practical middle path is to write the code as if pooled, with the tenant identifier everywhere, and deploy some tenants to their own stamp: vertically partitioned in Microsoft’s terms, bridge in AWS’s. It costs little if the isolation rule already lives in the service layer, and a great deal to retrofit if it does not.
On budget, tenancy is a property of the whole platform, not a line item. As a planning estimate, a production SaaS with authentication, subscription billing and a light admin sits in the $80k to $180k band, and a multi-surface platform with tenant administration, integrations and realtime features in the $150k to $350k and above band, consistent with Sigi’s guide to how much it costs to build a mobile app. Those are typical-scope figures, not a quote and not a figure attached to 3DLogistiX.
In what order should you build multi-tenancy?
- Define the tenant and its identifier before any other model, including whether a customer with several divisions is one tenant or several.
- Build identity so every session carries tenant context, then a data access layer that refuses to run without it, then the same identifier on cache keys, queue messages and realtime channels.
- Automate onboarding as one idempotent job, including billing and the first admin user.
- Add per-tenant telemetry, then rate limits and quotas, then asynchronous queues for heavy work.
- Put cross-tenant tests in continuous integration before the second customer signs, and reserve siloing for tenants whose contract or load requires it.
Related reading
The product built on this tenancy model is covered in how to build a warehouse management system, and the full architecture write-up is the 3DLogistiX warehouse platform case study. A marketplace is a multi-tenant platform whose tenants are vendors, so how to build a multi-vendor marketplace applies the same onboarding and scoping ideas. For the pipeline side, see Sigi’s DevOps and cloud engineering service. To scope a platform, start with SaaS development or custom software development, or talk to Sigi about the tenancy decisions in your product.

