AI System Design

Design a Multi-Tenant AI SaaS Platform

Step 1 / 9

Learn AI system design by building an AI product serving many separate customer organizations from shared infrastructure.

The numbers to beatper-tenant quotacontains the blast radiusspiking tenantthrottled at their own limitevery other tenantunaffected

In the interview room

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

Functional requirements

What it must do — agree on these before drawing a single box.

  • Serve tenants: answer each tenant user’s queries from shared infrastructure, scoped to their organization only.
  • Isolate data: every retrieval and data access is scoped to exactly one tenant, verified at the data layer.
  • Customize: per-tenant prompts, retrieval scope, and feature flags from config, on one shared runtime.
  • Meter usage: track LLM and infrastructure cost per tenant per request for usage-based billing.
  • Onboard / offboard: self-service tenant provisioning, and genuine, verifiable deletion when a tenant leaves.

Non-functional requirements

The qualities that shape the whole design — each one names the mechanism that buys it.

No tenant’s data ever surfaces in another’s answer
Tenant scoping enforced independently at the data layer — every query carries and verifies a tenant id, checked by the store itself, not trusted from upstream.
Survive a bug in any single isolation layer
Defense in depth — isolation enforced at both the API and data layers, so one missed check doesn’t become a full cross-tenant breach.
Different tenant behavior without N deployments
One shared runtime resolves per-tenant config (prompts, retrieval scope, feature flags) at request time; fixes ship once to everyone.
One tenant’s spike can’t degrade the rest
A Quota Enforcer applies per-tenant rate limits, so a noisy neighbor is throttled at their own boundary — shared infrastructure, not shared blast radius.
Bill fairly across wildly different usage
Per-tenant, per-request cost attribution tracks the real LLM/infra cost each tenant generates, as the basis for usage-based billing.
Meet data-residency / compliance rules
A Region Router directs a tenant’s requests and storage to region-specific infrastructure when their compliance requirements demand it.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

Independent data-layer scopingover trusting the API layer alone

A single enforcement point makes any bug in that one layer a full cross-tenant breach. The data store verifying tenant id on every query is an independent backstop the API layer can’t provide.

Shared runtime + per-tenant configover a separate deployed stack per tenant

Deploying a full stack per tenant means shipping every fix N times — unmanageable past a handful of customers. Config resolved per request differs behavior while code and fixes stay shared.

Per-tenant quotasover accepting cross-tenant impact as unavoidable

Throttle a spiking tenant at their own boundary and every other tenant is untouched. Shared infrastructure doesn’t have to mean a shared blast radius — the noisy-neighbor problem is solvable, not inherent.

Usage-based billing from per-tenant costover a flat rate for everyone

Flat pricing over wildly varying usage overcharges light users into churn and loses money on heavy ones. Tracking real per-tenant cost lets price track consumption and keeps margins predictable.

Genuine, verifiable deletionover marking the tenant inactive

A tenant’s data lives in embeddings, caches, backups, logs and replicas — deactivation leaves it all in place. Right-to-erasure compliance needs confirmed removal across every store the data touched.

What this teaches

Learn AI system design by building an AI product serving many separate customer organizations from shared infrastructure. An interactive guide covering why unscoped shared retrieval risks one tenant's private data leaking into another's answers, enforcing tenant isolation at the data layer (not application trust), per-tenant customization via configuration instead of duplicated infrastructure, noisy-neighbor prevention with per-tenant quotas, per-tenant cost attribution for accurate billing, data-residency routing for compliance, automated tenant onboarding, and defense-in-depth isolation that survives a bug in any single layer.

Key takeaways

  • An unscoped shared index risks one tenant's private data surfacing directly in another tenant's results — a severe breach, not a minor bug.
  • Tenant isolation is enforced independently at multiple layers (API and data store), so a bug in any one alone doesn't cause a full breach.
  • Per-tenant customization lives in configuration resolved at request time, on one shared runtime — not a separately deployed stack per tenant.
  • Per-tenant quotas contain the blast radius of any single tenant's traffic spike to that tenant alone.
  • Precise per-tenant cost attribution is the prerequisite for fair, usage-based billing across widely varying tenant usage patterns.
  • A region router transparently serves tenants with data-residency requirements from appropriate regional infrastructure.
  • Automated, self-service tenant onboarding is what lets the customer base scale independent of platform-engineering headcount.
  • Tenant offboarding requires genuine, verifiable deletion across every data store, not just marking a tenant inactive.

Concepts covered

  • Shared infrastructure, zero cross-tenant leakage
  • One shared config, one shared index
  • Every query, independently scoped
  • Different prompts, one shared runtime
  • One tenant's spike shouldn't degrade everyone else
  • Know exactly what each tenant actually costs
  • Some tenants' data can't leave a region
  • A new customer shouldn't need custom engineering
  • Defense in depth, and genuine deletion

Design a Multi-Tenant AI SaaS Platform — read the full walkthrough as text

the same steps, decisions & trade-offs, for reading, reference & search

The big idea

Shared infrastructure, zero cross-tenant leakage

Serving many separate customer organizations from one shared platform is efficient — until tenant A's private data ends up retrieved into tenant B's answer, or tenant C's traffic spike makes every other tenant's product feel broken. Multi-tenancy done right is invisible to every tenant; done wrong, it's a data breach or an outage waiting to happen.

We'll build isolation as a first-class, multi-layer property — not application-level trust — plus the operational realities of running one platform for many customers: customization without duplication, noisy-neighbor prevention, cost attribution, and compliance-driven data residency.

How to read this: Each step opens with a real design decision — make the call before I show you what ships. Watch the diagram grow, hover the boxes, and at the end introduce a scoping bug and spike a noisy neighbor to see what defense-in-depth and quotas actually catch. Hit Begin.

Step 1 · The baseline

One shared config, one shared index

Simplest version: every tenant's documents go into one shared vector index, and everyone uses the same prompt and configuration. What's the danger, specifically for a retrieval-augmented system?

Design decision: All tenants' documents share one unscoped vector index. What's the specific danger?

The call: A retrieval query from Tenant B could return and surface Tenant A's private documents in Tenant B's answer — a direct data leak between completely separate customer organizations, some of whom may be direct competitors. — Without tenant scoping enforced on retrieval, similarity search has no concept of "whose data this is" — it just finds the closest-matching vectors regardless of tenant, meaning one tenant's private, confidential documents can genuinely surface in another tenant's query results. For a B2B SaaS product, this is often the single most catastrophic possible failure.

An unscoped shared index risks one tenant's private documents surfacing directly in another tenant's retrieval results — a severe data breach, not a minor quality issue. Tenant isolation has to be enforced at the data layer, from the very first design decision, not treated as an afterthought.

Multi-tenancy's central risk is invisible until it isn't: A shared, unscoped system can appear to work fine in testing (if test data happens not to overlap meaningfully) while carrying a live, catastrophic leakage risk the moment two tenants' real data genuinely differ in ways retrieval can conflate — this is exactly why isolation needs to be a designed guarantee, not an assumption.

Step 2 · Enforce isolation at the data layer

Every query, independently scoped

Fix Step 1: every retrieval and every data access must be scoped to exactly one tenant. Should this scoping be trusted to the application layer alone?

Design decision: Tenant scoping needs to be enforced somewhere. Is trusting the application/API layer alone sufficient?

The call: No — enforce tenant scoping independently at the DATA layer itself (every query to the data store includes and verifies a tenant id, checked by the store, not just trusted from upstream), in addition to the API layer. — Independent, redundant enforcement at the data layer means even if the API layer's own tenant check has a bug, the data store's OWN check still blocks the cross-tenant access — a genuine defense-in-depth property that a single point of enforcement can never provide.

Enforce tenant scoping independently at the data layer, not just trusted from the API — every query to Tenant-Isolated Data carries and verifies a tenant id, checked by the store itself. This gives genuine defense-in-depth: a bug at any single layer doesn't automatically mean a full cross-tenant breach.

Enforce boundaries in the platform, redundantly, not just once: This echoes a theme from agent tool-permission enforcement — a boundary that matters shouldn't depend on a single point of correctness. For tenant isolation specifically, the stakes (a full data breach) justify enforcing the check at more than one independent layer.

Step 3 · Customization without duplicated infrastructure

Different prompts, one shared runtime

Tenants want different system prompts, different knowledge-base scopes, maybe different feature sets. Does each tenant need its own separately-deployed copy of the whole application stack?

Design decision: Tenants want meaningfully different behavior. Does each need a fully separate deployed stack?

The call: No — run one shared runtime, and resolve tenant-specific behavior (prompts, retrieval scope, feature flags) from Per-Tenant Config at request time, so the underlying application code and infrastructure stay shared while behavior genuinely differs per tenant. — A shared runtime with tenant-scoped CONFIGURATION resolved per request gives each tenant meaningfully different behavior — different prompts, different feature flags, different retrieval scope — without needing to deploy or maintain a separate copy of the actual application for each one. Updates and fixes ship once, to everyone, automatically.

Use one shared runtime with Per-Tenant Config resolved at request time — prompts, retrieval scope, and feature flags differ per tenant, while the underlying application code and infrastructure remain shared. Tenant admins configure their own instance through this layer, without needing platform engineering to deploy anything separately.

Separate what varies from what stays shared: The same code-vs-configuration separation used for feature flags and prompt management elsewhere applies here at the tenant level: what SHOULD differ per tenant (prompts, scope) lives in configuration; what SHOULDN'T need to differ (the application logic itself) stays one shared, maintainable codebase.

Step 4 · Prevent noisy neighbors

One tenant's spike shouldn't degrade everyone else

All tenants share the same underlying infrastructure. One tenant suddenly sends 50x their normal traffic. Should that be allowed to affect other tenants' latency or availability?

Design decision: One tenant spikes traffic dramatically on shared infrastructure. Should other tenants feel the effect?

The call: No — enforce per-tenant rate limits and resource quotas, so a spiking tenant is throttled at their own boundary while every other tenant's experience on the shared infrastructure remains unaffected. — Per-tenant quotas contain the blast radius of any single tenant's traffic pattern to that tenant alone — the spiking tenant experiences their own throttling, while the shared infrastructure's capacity for every other tenant stays exactly as available as before.

Add a Quota Enforcer: per-tenant rate limits and resource quotas mean a traffic spike from one tenant is contained to throttling at THEIR boundary, with zero impact on the latency or availability every other tenant experiences on the same shared infrastructure.

Shared infrastructure shouldn't mean shared blast radius: This is the same fair-share/quota principle that shows up across very different domains in this series (dating-app fairness, GPU scheduling, online-judge queueing) — whenever multiple parties share a finite resource, per-party bounds are what keep one party's behavior from degrading everyone else's experience.

Step 5 · Attribute cost per tenant

Know exactly what each tenant actually costs

Tenants have vastly different usage patterns — some send a handful of requests a day, others thousands. Should pricing be flat regardless of actual usage?

Design decision: Tenant usage varies enormously. Should billing be a flat rate regardless of actual consumption?

The call: No — track exact LLM and infrastructure cost per tenant per request, and use that Cost Attribution data as the basis for accurate, usage-based billing. — Precise per-tenant cost tracking means pricing can actually reflect real consumption — light users pay less, heavy users pay proportionally more, and the platform's margins stay predictable regardless of how usage patterns vary across the tenant base.

Track Cost Attribution precisely per tenant, per request — the real LLM and infrastructure cost each tenant actually generates. This becomes the basis for usage-based billing that fairly reflects real consumption, rather than a flat rate that over- or under-charges depending on how each tenant actually uses the product.

Billing accuracy depends on cost visibility: You can't price fairly what you don't measure precisely — per-tenant cost attribution is the prerequisite for any pricing model more sophisticated than an undifferentiated flat rate, and it's also simply useful operationally for knowing which tenants and use cases are actually profitable.

Step 6 · Data residency and compliance

Some tenants' data can't leave a region

An enterprise tenant in the EU requires their data to stay within EU infrastructure for regulatory reasons. Can they be served from the same global deployment as every other tenant?

Add a Region Router that directs a tenant's requests and storage to region-specific infrastructure when their compliance requirements demand it — a tenant with data-residency requirements is transparently routed to and stored in the correct region, while tenants without such requirements continue using the default global deployment. This is a per-tenant configuration choice, not a platform-wide architectural fork.

Compliance requirements are a per-tenant property, not a platform-wide one: Not every tenant needs data residency guarantees, so building the platform to ROUTE tenants that do need it to appropriate infrastructure — rather than either ignoring the requirement entirely or forcing every tenant through the most restrictive regional constraint — serves both populations correctly.

Step 7 · Automated tenant onboarding

A new customer shouldn't need custom engineering

A new enterprise customer signs up. Should provisioning their isolated configuration, storage, and quotas require manual, bespoke engineering work each time?

Make onboarding self-service and automated: creating a new tenant's isolated config entry, data-store scope, and default quotas is a fast, automated provisioning flow the Tenant Admin can trigger themselves — not a manual, per-customer engineering task that doesn't scale as the platform grows its customer base.

Operational scale requires automated provisioning: A platform that requires manual engineering effort to onboard every new tenant caps its own growth at whatever rate engineers can manually provision customers — automating the entire provisioning path is what lets the tenant base grow independent of platform-team headcount.

Step 8 · The sharp edges

Defense in depth, and genuine deletion

Two of the highest-stakes real-world requirements: a bug in any single isolation layer must not cause a full cross-tenant breach, and when a tenant leaves, their data needs to actually, verifiably disappear.

Isolation is enforced independently at multiple layers — API-level tenant scoping AND data-layer tenant verification — so a bug in either one alone doesn't produce a full breach, as demonstrated by the Step 2 chaos scenario. For tenant offboarding, deletion must be genuine and verifiable across every store the tenant's data touched (documents, embeddings, config, logs, backups) — not simply marking the tenant inactive while their data quietly persists, which fails compliance requirements like the GDPR right to erasure.

Design for the unhappy path: A scoping bug at one layer → caught by independent enforcement at another. A noisy neighbor → contained by per-tenant quotas. A departing tenant → genuinely, verifiably deleted, not just deactivated. A multi-tenant platform that only stays safe when every layer works perfectly is a demo; one that survives a bug in any single layer is a product.

You did it

You just designed a multi-tenant AI SaaS platform.

  • An unscoped shared index risks one tenant's private data surfacing directly in another tenant's results — a severe breach, not a minor bug.
  • Tenant isolation is enforced independently at multiple layers (API and data store), so a bug in any one alone doesn't cause a full breach.
  • Per-tenant customization lives in configuration resolved at request time, on one shared runtime — not a separately deployed stack per tenant.
  • Per-tenant quotas contain the blast radius of any single tenant's traffic spike to that tenant alone.
  • Precise per-tenant cost attribution is the prerequisite for fair, usage-based billing across widely varying tenant usage patterns.
  • A region router transparently serves tenants with data-residency requirements from appropriate regional infrastructure.
  • Automated, self-service tenant onboarding is what lets the customer base scale independent of platform-engineering headcount.
  • Tenant offboarding requires genuine, verifiable deletion across every data store, not just marking a tenant inactive.
built so a bug in one layer never lets tenant A see tenant B's data — make the calls, spike a noisy neighbor, run the gauntlet.
Finished this one? 0 / 61 AI System Designs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More AI System Designs