A tenant is the customer boundary in a SaaS product: a group of users, usually one organisation, that shares your product while getting its own data, configuration, plan, limits and bill. Users log in; tenants sign contracts. Almost every later decision in a multi-tenant system hangs off this one entity, so define it precisely before you draw a single box.
Picture it first: a co-working building
Think of a co-working building in Bengaluru. The building company runs the lifts, power, security desk and front office. Each company that leases space, say a 12-person fintech start-up, is a tenant: it gets a lockable suite, access cards for its people, its own rules for booking rooms, a plan (hot desks or a cabin), limits (at most 20 cards) and its own monthly invoice.
People are not tenants. A freelance chartered accountant carries cards for three client companies, and her card opens different doors in each. The security desk decides which suite you may enter from the card it issued, not from what you say at the desk. And when a company moves out, it gets time to pack before the suite is cleared and the locks are reset.
Map it back. The building is your SaaS product and the building company is you, the provider, with a shared control plane. A suite is a tenant’s data and configuration, an access card is a signed token naming the tenant, one card per company is a membership with a role, and the security desk is your API gateway. The lease is the plan and its limits, and moving out is offboarding.
Tenant, user, account, organisation, workspace
Five words get used loosely in SaaS. Pin them down, because the bugs come from mixing them up.
Tenant. The unit you isolate, configure, entitle and bill. AWS’s SaaS guidance is plain: tenants are not individual users, and a tenant is likely associated with many users. Sign-up creates the tenant and its first admin, who invites everyone else.
User. An identity that authenticates: a person, or a machine such as a CI bot. The login lives in an identity provider, yours or the customer’s via single sign-on, independent of any tenant. GitHub makes the split explicit: people sign in to user accounts, nobody can sign in to an organisation, and one user can belong to many organisations.
Membership. The link (user, tenant, role), and the entity people forget. Priya can be an admin in one tenant and a read-only guest in another only if the role sits on the membership, not on the user.
Organisation. The real-world company. Usually it is one tenant, but Azure’s guidance lists reasons for several: divisions with different requirements, a presence in several countries, or separate development and production instances.
Workspace or project. A container inside a tenant: channels, boards, repositories. Whether it is a tenant depends on the product. A Slack workspace on a smaller plan stands alone; on Slack’s Enterprise plans, workspaces are migrated into one Enterprise organisation that holds org-wide settings and requires single sign-on.
Account. The most overloaded word: a login, a billing customer or a cloud account. Say which you mean.
Tenants also form hierarchies. GitHub’s enterprise accounts manage policy and billing for several organisations, while each organisation keeps its own repositories and members, so the isolation boundary and the billing boundary sit at different levels of one tree. Partners add another axis: a CA firm keeping the books of 40 small businesses in a Zoho-style accounting SaaS needs one login that reaches 40 tenants, while the 40 sets of books never mix. Model that with memberships and a parent_tenant_id, never by merging tenants.
| What it is | Who creates or owns it | What is scoped to it | Typical cardinality | |
|---|---|---|---|---|
| Tenant | The customer boundary you isolate, configure, entitle and bill | Created at sign-up; run by the customer’s tenant admins | Data, settings, plan, limits, keys, region, invoices, audit log | One per customer contract; many users each |
| User | An identity that authenticates: a person or a machine | Your identity provider, or the customer’s via SSO | Credentials, MFA, profile | Belongs to zero, one or many tenants |
| Membership | The link (user, tenant, role) | A tenant admin’s invite, or SSO provisioning | The role and permissions inside that tenant | One per user per tenant |
| Account | An overloaded word: a login, or a billing customer | Depends on the product | Say which you mean | Varies |
| Organisation | The real-world company or group | Exists outside your system | The contract, legal name, its own identity provider | Usually one tenant; sometimes several |
| Workspace or project | A container inside a tenant | Tenant admins or members | Channels, boards, repositories, finer roles | Many per tenant |
Same word, different meaning
Vendors use these words for their own products too. In Auth0’s documentation, your tenant is your own Auth0 instance, and your B2B customers are Organizations inside it. Map a vendor’s terms onto yours before you design anything.
B2B, B2C and B2B2C
Who your tenant is depends on who pays and who shares data.
B2B. The tenant is the customer organisation; users are its employees plus invited guests. This is the clean case the rest of the module assumes.
B2C. Azure’s guidance notes that each consumer might be a tenant, but families, clubs or friends may need to manage data together, so a music service might treat individual and family plans as different shapes of tenant. Many consumer apps have no tenant at all and key every row by user, which bites later: a family or team plan then means inserting a tenant above the user and re-keying every shared table while the app stays live.
B2B2C. Your tenant serves its own customers: a store builder whose merchants sell to shoppers, a school ERP whose parents log in, a clinic platform whose patients book appointments. The tenant now has two user pools, staff and end customers, both inside its boundary. Decide early whether an end customer’s login is per tenant (simpler, nothing to leak) or shared across tenants (one login across many stores, but a cross-tenant identity to guard).
Model a tenant even when you don’t need one
In a pure consumer app, still create an account entity and give each new user a “tenant of one”. It costs one table and one join today, and turns the future family or team plan into a feature instead of a migration.
Single-tenant and multi-tenant
Single-tenant means a deployment serves one tenant; multi-tenant means one deployment serves many, and the application tells them apart.
AWS’s SaaS guidance avoids the first term: a stack per tenant is still multi-tenant SaaS if every stack shares onboarding, identity, billing and one release, so it calls dedicated parts silo and shared parts pool. Azure separates tenants (logical customers) from deployments (physical copies of the stack), with a mapping table so a tenant can move. How much each tenant shares is the next lesson, tenancy models: silo, pool and bridge; this one is about the tenant itself, which exists under any model.
What hangs off a tenant
The tenant is the unit of almost every cross-cutting concern. The control plane keeps a tenant record in a catalog, like this:
tenant_id: 0b6f2c1e-8d4a-4f7e-9b3a-5c2d7e1f9a40 # immutable and opaque: the only key
slug: acme-retail # mutable label: acme-retail.example.com
display_name: Acme Retail Pvt Ltd
status: active # provisioning | trial | active | suspended | offboarding | deleted
plan: business # drives entitlements and feature flags
limits: { seats: 50, api_calls_per_min: 600, storage_gb: 200 }
home_region: ap-south-1 # data residency
deployment: stamp-07 # which copy of the stack holds its data
kms_key: tenants/acme-retail # its own encryption key
sso: saml/acme-okta # its identity provider, if it brings one
parent_tenant_id: null # set for enterprise or partner hierarchies
Each field drives a concern scoped per tenant:
- Isolation: its data is reachable only inside its boundary (multi-tenancy and isolation, multi-tenant data).
- Configuration and feature flags: branding, SSO, workflow rules, and flags evaluated per tenant, so a feature can reach five friendly tenants first (feature flags).
- Entitlements: the plan decides which features are on. Resolve them once from the tenant record, not with
if plan == "pro"scattered through the code. - Limits and quotas: seats, API calls per minute and storage, so one tenant cannot starve the rest (noisy neighbours and fairness, rate limiting).
- Billing and metering: tenant-tagged usage events roll up into its invoice (metering and usage-based billing).
- Data residency and keys: the home region bounds where data and backups live, and a key per tenant lets you revoke or destroy one tenant’s data alone (encryption and key management).
- Backup, restore, export and deletion: all per-tenant requests, and painful if data isn’t tagged.
- Observability and support: per-tenant error rates and latency answer “is it just us?” (observability); tickets, SLAs and staff access are scoped to one tenant.
Tenant context: from token to row
Tenant context answers “which tenant is this request for?” and travels with the request from the edge to the database. AWS calls the binding of a user to a tenant the SaaS identity: after authentication you know who the user is and which tenant they act in, because the identity provider puts tenant claims into the token.
- Sign in. The user authenticates (OAuth 2.0 and OpenID Connect); a user with several tenants picks one, and the token is issued for it. Auth0’s Organizations feature, for example, adds an
org_idclaim to ID and access tokens. - Verify at the edge. The API gateway checks signature, expiry, issuer and audience (tokens and JWTs), reads the tenant claim, and checks status and plan in a cached copy of the catalog. Client-sent tenant IDs are stripped, and a subdomain naming a different tenant gets a 403.
- Carry it inward. Services read the tenant from a request-scoped context, filled from the forwarded token or a header only the gateway can set. AWS’s SaaS Lens makes the performance point: with 100 microservices, each should apply tenant context from the token without a round trip to another service.
- Stamp everything. Everything the request writes or emits carries the tenant ID, and workers restore context from the message.
In code, the edge of every service does something like this:
function tenantContext(req: Request): TenantContext {
const claims = verifyJwt(req.headers.authorization); // signature, expiry, issuer, audience
const tenantId = claims.tid; // from the token, never from the request
delete req.headers["x-tenant-id"]; // a client-sent tenant never travels inward
const tenant = tenantCatalog.getCached(tenantId); // status, plan, region, limits
if (!tenant || tenant.status === "deleted") throw forbidden("unknown tenant");
const hint = subdomainOf(req.host); // which tenant the user meant to open
if (hint && hint !== tenant.slug) throw forbidden("tenant mismatch"); // 403, and log it
if (tenant.status === "suspended" && req.method !== "GET") throw suspended();
return { tenantId, userId: claims.sub, roles: claims.roles, plan: tenant.plan };
}
Hints are not identity
A subdomain, path or X-Tenant-Id header says which tenant a user wants; only the signed token says which tenant they may use. If a hint names a different tenant from the claim, return 403 and log it. Auth0’s API guidance agrees: validate org_id against organisations you know, and segment data access by it.
The “tenant ID everywhere” rule
- Rows and objects: a
tenant_idcolumn on every shared table, and a tenant prefix on every object path. - Cache keys:
t_7f3a:cart:u_91, nevercart:u_91(distributed caching). - Messages: the tenant ID in the envelope of every queue message and event.
- Logs and traces: a structured
tenantfield on every line and span. - Metrics, carefully: one counter labelled with 10,000 tenants × 30 endpoints × 5 status classes is 1.5 million time series. Label metrics by tier, give the largest tenants their own series, and keep full tenant IDs in logs, traces and metering events.
Put this in shared libraries (a logger, cache client, database session and producer that add the tenant) so nobody has to remember.
IDs, names and subdomains
A tenant carries three identifiers, and only one is safe as a key: the tenant ID (opaque, immutable, generated by you, never reused), the slug or subdomain (acme-retail.example.com, mutable) and the display name (it changes with a rebrand). Never key data by the subdomain:
- Renames. With an immutable ID, a rebrand is one catalog update and a redirect; with the name as the key, it is a migration of every table and object path.
- Reuse. Subdomains are first-come and freed when a tenant leaves. Azure’s domain-name guidance walks through the attack: Fabrikam offboards but leaves a DNS record pointing at its old subdomain, an attacker signs up a new tenant named
fabrikam, and inherits traffic meant for Fabrikam. Anything still keyed by the name now resolves to the newcomer. - Guessability. OWASP’s first example of its top API risk is a hosted e-commerce platform where swapping the shop name in
/shops/{shopName}/revenue_data.jsonexposed the sales data of thousands of stores. OWASP recommends random, unpredictable IDs: no substitute for authorisation, but an end to trivial enumeration.
Auth0 likewise prefers organisation IDs to names when validating tokens, and Azure’s identity guidance says to store user-to-tenant mappings against immutable identifiers. Store it compactly: a UUID is 128 bits, so 16 bytes in a native UUID column against 36 characters as text (32 hex digits and 4 hyphens). Over 1 billion rows that is 20 bytes × 1 billion ≈ 20 GB saved per copy, before indexes repeat it.
The tenant lifecycle
Every transition between these states is a workflow with side effects.
Provisioning. Onboarding creates the tenant record, the first admin and membership, default roles and settings, the plan’s limits, a key and, for siloed tiers, infrastructure; AWS describes it as an orchestrator over the other core services. Steps can fail halfway, so make each idempotent and the flow resumable (multi-step workflows). The gateway rejects the tenant’s requests until provisioning completes.
Trial. Azure lists the questions: shared infrastructure, service levels, caps, and how trial data carries over. The simple answer is an ordinary tenant on a trial plan, so buying is a plan change, not a migration.
Plan changes. Upgrades and downgrades update entitlements and limits at once; some also move the tenant to dedicated infrastructure, as the tenancy models lesson describes. On a downgrade, make data over the new limit read-only, not deleted.
Suspended. Payment fails or abuse is detected. Azure separates this temporary deactivation from offboarding: data is kept, logins become read-only or blocked, jobs and webhooks pause, and paying again reactivates the tenant in seconds.
Offboarding. The customer cancels or a suspension runs out. Open an export window, then delete from every store: database, object storage, search indexes, caches, analytics copies, and logs as far as policy says. Backups are rarely rewritten, so the data disappears as they age out, or at once if you destroy the tenant’s own key. Azure asks you to set the retention period, including any legal minimum or maximum, and whether the tenant can return within it. Release the subdomain only after a cooling-off period.
Merge and split. Acquisitions and divestments are far easier when the tenant is an ID, not part of names and paths.
These are slow, multi-step, audited workflows across billing, identity and infrastructure, so the control plane owns them; the data plane only reads the tenant’s current status from a cache.
Going deeper: how tenant boundaries leak
Most cross-tenant leaks come from a few habits, and interviewers probe each.
Tenant from user input. The API takes the tenant from a header, path or body, or fetches an object by ID without checking its owner. That is Broken Object Level Authorization, first in OWASP’s 2023 API Top 10, applied across tenants; OWASP adds that comparing the token’s user ID with an ID in the request covers only a small subset of cases. Fix it in three layers: the tenant comes from the verified token, every query is scoped by it (WHERE tenant_id = ? AND id = ?), and row-level security in the database is the backstop. Add tests that log in as tenant B, try to read tenant A’s objects, and fail the build if any succeed.
User treated as tenant. Data keyed by user_id leaves with the employee who created it, and roles stored on the user leak: Priya, an admin at Bharat Traders, becomes an admin at Acme too. Key data by tenant, and keep roles and tenant-specific profile fields on the membership; Azure warns that what tenant A adds to a shared user’s profile must not show up for tenant B.
Admin access that bypasses tenant checks. An internal console running as a superuser is one bug away from showing everyone’s data. AWS separates the provider’s admin users from tenant users. Give staff their own identities and let them impersonate one tenant at a time: time-boxed, tied to a ticket, ideally customer-approved, and written to that tenant’s audit log.
Background jobs that lose context. A message with no tenant ID, a nightly “all tenants” query on a privileged connection, or a worker that keeps the last job’s tenant on a reused thread. Stamp every envelope, fan “all tenants” jobs out into one job per tenant, and set and clear the context per job, scoped to the transaction rather than the connection.
Caches keyed without the tenant. If invoice IDs are per-tenant sequences, invoice:1042 exists in many tenants, and whoever fills the cache first wins. A CDN that caches a tenant’s page under a tenant-free URL fails the same way. Prefix keys in the cache client and mark per-tenant responses private.
Analytics across tenants. Internal cross-tenant dashboards are normal, but customer-facing reports must filter by tenant, benchmarks against “similar businesses” need aggregation and contractual permission, and residency rules cover the warehouse too.
In the interview
Name the layers in one breath: “The tenant comes from the signed token, checked against the membership at the gateway. Every query, cache key and message is scoped by it, and row-level security is the backstop, so one missing WHERE clause isn’t a breach.”
Cheat sheet
| Term | Remember it as |
|---|---|
| Tenant | The customer boundary: data, config, plan, limits, keys, region, bill |
| User | An identity that logs in; can belong to many tenants |
| Membership | (user, tenant, role); roles live here, not on the user |
| Organisation | The real company; usually one tenant, sometimes several |
| B2C | A tenant of one, a household, or none; still model an account |
| B2B2C | The tenant’s own customers live inside its boundary |
| Tenant context | From the signed token claim, never from a header, path or body |
| Tenant ID everywhere | Rows, object keys, cache keys, messages, logs, traces, meters |
| Identifiers | Opaque immutable ID as the key; slug and name are labels |
| Lifecycle | Provisioning, trial, active, suspended, offboarding, deleted; the control plane owns it |
| Biggest bug | Tenant from user input, giving a cross-tenant read (BOLA) |
How to say it in the interview
“A tenant is the customer boundary: usually a company, with its own data, settings, plan, limits and bill, and many users. Memberships link users to tenants with a role, so a consultant can reach five tenants with one login. At sign-in the token gets a tenant claim; the gateway verifies it, ignores any tenant in the request, and sets the request context. Every row, cache key, message, log line and usage event then carries an immutable tenant ID, never the subdomain, and row-level security enforces it again in the database. The control plane owns the lifecycle, from onboarding to offboarding.”
Can one user belong to several tenants? Yes, through a membership table that holds the role. A token is issued for one tenant at a time, and switching tenants means a new token, so a request is never ambiguous.
Why not identify the tenant by subdomain? It can be renamed, or reclaimed after a tenant leaves. Use it to choose which tenant to sign in to, check it matches the token’s claim, and store everything under the immutable ID.
How does a background job know its tenant? From the tenant ID in the triggering message’s envelope. The worker sets the context before doing anything and clears it afterwards; an “every tenant” job fans out into one job per tenant.
What happens when a tenant stops paying? Suspension, not deletion: data kept, logins read-only or blocked, jobs paused, instant reactivation on payment. After a grace period comes offboarding: an export window, deletion everywhere, and backups that age out or become unreadable once its key is destroyed.
Does a consumer app need tenants? It can treat each user as a tenant of one. I’d still create an account entity on day one, because adding family or team plans later otherwise means re-keying every table.
Where to go next
- Tenancy models: silo, pool and bridge: how much of the stack each tenant gets to itself.
- Control plane vs data plane: the shared layer that runs onboarding and the lifecycle.
- Routing requests to tenants: subdomains, paths and tokens, and finding the right deployment.
- Multi-tenant data: database, schema or row per tenant, and row-level security.
- Noisy neighbours and fairness: per-tenant limits that keep a shared pool healthy.
- Metering and usage-based billing: turning tenant-tagged usage into invoices.
- Multi-tenancy and isolation: tenant-scoped credentials and leak tests.
- Design a multi-tenant SaaS platform: all of this in one design.
References and further reading
- Azure Architecture Center: Tenancy models for a multitenant solutionlearn.microsoft.com“Define a tenant”: B2B tenants map to customer organisations (sometimes several per customer), B2C tenants may be people or families, and tenants are distinct from deployments.
- Azure Architecture Center: Tenant life cycle considerations in a multitenant solutionlearn.microsoft.comTrials, onboarding questions, deactivation versus offboarding, retention periods, re-onboarding, and merging or splitting tenants.
- Azure Architecture Center: Architectural considerations for identity in a multitenant solutionlearn.microsoft.comA tenant ID claim in the token, users who belong to several tenants and switch between them, immutable IDs for user-to-tenant mappings, and profile data leaking across tenants.
- Azure Architecture Center: Considerations for domain names in a multitenant solutionlearn.microsoft.comPer-tenant subdomains in a first-come namespace, and the dangling-DNS takeover that follows when an offboarded tenant’s name is claimed by someone else.
- AWS Well-Architected SaaS Lens: Identity and access management (SaaS SEC 1)docs.aws.amazon.comSaaS identity binds each user to a tenant; tenant claims in the JWT let 100 microservices apply tenant context without a round trip to another service.
- AWS SaaS Architecture Fundamentals: Core servicesdocs.aws.amazon.comTenants are not users; a tenant service holds tenant policies, attributes and state; onboarding orchestrates users, tenant, policies and resources; provider admins are separate from tenant users.
- OWASP API Security Top 10 (2023): API1 Broken Object Level Authorizationowasp.orgThe number-one API risk, its shop-name example on a hosted e-commerce platform, why comparing user IDs is not enough, and the advice on random IDs and authorization tests.
- Auth0 Docs: Work with tokens and Organizationsauth0.comAn org_id claim in ID and access tokens, validating it against known organisations, preferring IDs to names, and segmenting API data access by it.
- GitHub Docs: Types of GitHub accountsdocs.github.comPeople sign in to user accounts, never to organisations; a user can belong to many organisations; enterprise accounts manage policy and billing for several organisations.
- Slack Help Center: Enterprise organization launch guideslack.comExisting workspaces, each with its own URL and ID, are migrated into one Enterprise organisation, where single sign-on is required.