Your tenant’s login succeeds, its database queries look correct, and its Kubernetes namespace exists. Then an export worker fetches another customer’s file. Which boundary actually failed?

That hypothetical incident is a useful opening for a staff engineer multi-tenant system design interview. AWS distinguishes tenant isolation from authentication and authorization: an authenticated user can still reach another tenant’s resources unless access is scoped by tenant context.

Build your answer around three questions: who owns this resource, where does that owner’s workload run, and how can ownership remain enforceable while the workload moves? The following playbook uses a proposed document-workspace SaaS, with shared application services and customer-specific documents, search, and exports. Its examples and interview timing are practice recommendations, not hiring statistics.

1. Define the tenant contract before drawing infrastructure

Ask whether a tenant means a company, a workspace, or an individual subscription. Can one person belong to several tenants? Are documents ever intentionally shared across organizations? Do customers execute arbitrary code, or only call your application? These answers determine the threat model.

For the workspace example, propose an immutable tenant ID, a separate user ID, and explicit membership records. A selected workspace is a request input that the server validates against membership. Neither an email domain nor a client-supplied header establishes ownership. Resolve object access against both the tenant and the object, following OWASP’s recommendation to check permissions on every request.

Write three invariants on the whiteboard: unauthorized cross-tenant reads and writes are rejected; each mutable resource has an unambiguous owner; and only one placement may accept a tenant’s writes during a move. Define performance isolation separately. A slow neighbor and a leaked document need different remedies.

A model opening answer

“I’ll treat the workspace as the tenant. Users may join multiple workspaces, so the server validates the active membership before creating tenant context. I’ll start with pooled resources, identify the enforcement point at each resource boundary, and preserve a path to dedicated placement.”

Follow with availability, residency, tenant size distribution, deletion, and restore requirements. Avoid committing to a deployment model until you know which requirements are mandatory.

Make support access a named exception to the ordinary path. For this design, propose time-limited access to one tenant, an explicit reason, and an audit trail that records the acting operator separately from the customer identity. If documents can be shared externally, represent that grant explicitly. Do not silently reinterpret a shared document as having two owners. Ask who may revoke the grant, which cached representations must disappear, and whether existing exports remain downloadable after revocation.

2. Choose pool, silo, or bridge per resource

Use precise terms, then explain your choice:

  • Silo: AWS’s silo model dedicates a resource stack to a tenant. It provides a clearer infrastructure boundary while adding provisioning, idle-capacity, and fleet-management costs.
  • Pool: AWS’s pool model shares resources across tenants. It trades greater utilization and centralized operation for more demanding resource-level isolation and shared failure exposure.
  • Bridge: AWS’s bridge model combines dedicated and pooled resources. Choose boundaries independently for compute, storage, and other services.

For this exercise, propose pooled application services and pooled database shards for ordinary workspaces. Allow a dedicated database or deployment for a customer with an explicit requirement. Keep the tenant ID stable across both paths so business logic does not confuse identity with location.

A dedicated database does not resolve the shared application’s access checks. Demonstrate the remaining route from an authenticated request to the correct database credentials. Also explain whether dedicated placement separates hosts, databases, accounts, or only schemas; the word “dedicated” needs an object.

3. Make tenant placement a control-plane decision

Separate ordinary document traffic from tenant provisioning and relocation. Microsoft’s control-plane guidance assigns tenant configuration, lifecycle management, placement, and rebalancing to management components. Treat that plane as privileged infrastructure, with narrower operator access than the application.

Propose a directory record containing tenant ID, region, stamp, database shard, isolation tier, lifecycle state, and placement epoch. The epoch is a monotonically increasing version used by your proposed protocol to reject stale routing. An ordinary user cannot change the directory to choose another customer’s storage.

A stamp is a repeated deployment unit. Microsoft’s Deployment Stamps pattern describes routing through a tenant-to-stamp mapping. In your design, first filter placements by residency and required isolation, then select among eligible units using measured headroom. Record why the placement was chosen.

Keep database sharding distinct from full deployment replication. Microsoft’s storage guidance notes that database shards can contain one or more tenants without duplicating the rest of the infrastructure. You can move storage independently if your routing and credentials support it.

For a directory outage, propose bounded use of cached mappings for active tenants, while blocking new placement changes. Cached mappings alone cannot enforce suspension or moves: storage must check an authoritative write fence. Specify how that fence remains available and what happens when it cannot be checked.

Also describe recovery from a partially completed onboarding operation. Use a durable operation record with retryable steps: reserve placement, provision resources, apply policies, verify access, then mark the tenant active. Keep failed tenants inaccessible while cleanup or retry proceeds. An idempotent provisioning API should recognize its previous work. This gives the interviewer an operational path from “we have a control plane” to a customer who can safely use the product.

4. Explain row-level security’s actual boundary

“Add tenant_id to every query” is an application convention. PostgreSQL row-level security adds a database policy, but its execution role matters. PostgreSQL 16 documents that superusers and BYPASSRLS roles bypass RLS; table owners normally do too. FORCE ROW LEVEL SECURITY subjects the owner to policies, without removing the other bypasses.

For pooled tables, propose a restricted application role and tenant-aware policies for both visibility and permitted changes. Keep migration credentials separate. Include tenant ownership in relational keys so a child cannot reference another tenant’s parent. Test the exact production role, including insert, update, join, and missing-context cases.

Set validated tenant context inside an explicit transaction. SET LOCAL lasts only through that transaction. PgBouncer transaction pooling releases the server connection afterward and does not preserve arbitrary session assumptions. Exercise your driver and pool configuration together.

State the limit: an application role capable of setting tenant context can select the wrong context if compromised. RLS using that context guards against omitted predicates; it does not independently authenticate the tenant. Your answer must keep the server-side membership check and the database policy connected.

Describe a negative test in ordinary language: create identical document IDs in two tenants, alternate requests through the same connection pool, and deliberately omit an application predicate. Expect the database policy to preserve the boundary. Then attempt a cross-tenant insert and a background update without context. Test permitted access too, so a policy that rejects everything cannot masquerade as successful isolation.

5. Treat Kubernetes namespaces as one layer

A namespace identifies a management boundary, not a complete tenant security design. Kubernetes’ multi-tenancy documentation requires additional access controls, networking configuration, and security practices around namespace isolation. It also notes that pods can communicate by default.

If this design runs tenant-specific workloads, propose restricted service accounts, default-deny network rules, reviewed exceptions, and separate credentials. NetworkPolicy has no effect without a supporting network implementation. Show a connectivity test, not merely a YAML object.

If customers execute untrusted code, revisit whether shared nodes meet the threat model. If they only use your shared document application, explain which workloads need tenant-specific namespaces at all. Match the boundary to the attack surface instead of creating infrastructure to decorate the diagram.

Practice explaining your isolation boundary, then ask Interview Copilot for a follow-up about a stale placement cache or a worker running with the wrong tenant context.

Practice your system design answer

6. Carry tenant identity through caches, objects, and jobs

Trace one document export end to end. The request validates membership, reads metadata, loads objects, starts a job, and stores a download. Put an enforcement decision at each arrow. A database policy cannot protect an unrelated cache or object store.

Cache and object boundaries

Propose cache keys containing tenant ID, resource ID, representation version, and any authorization dimension that changes the result. Reject a key helper that accepts an unvalidated tenant string. Redis ACLs can restrict commands and key patterns; a shared all-tenant credential still relies on the application choosing the right key.

For object storage, bind object metadata and permitted paths to the tenant. S3 access points provide distinct permissions and network controls, with their policies operating alongside bucket policies. Explain how you prevent an alternate access path from bypassing the intended restriction.

Authorize an export before issuing its download link. S3 presigned URLs function as bearer tokens. For this design, use short-lived links, avoid placing them in logs, and define revocation behavior.

Background work is another request

Propose a job envelope with tenant ID, operation ID, resource IDs, and placement epoch. The worker resolves current placement and checks tenant lifecycle state before mutation. Keep the operation ID stable across a move to make duplicate handling survive relocation.

SQS standard queues can deliver duplicates, and S3 event notifications use at-least-once delivery. Design tenant-scoped idempotency and lifecycle checks so a replay cannot resurrect a deleted workspace or write to an obsolete shard.

For telemetry, propose recording the validated tenant ID, placement epoch, and operation ID on request traces and migration records. Keep document content and download credentials out of those records. Use the evidence to answer a precise incident question: which tenant, which placement, which accepted mutation? Define access to this operational data alongside access to customer documents.

7. Use capacity math to defend placement

Give a small, explicitly hypothetical example. Suppose you have 10,000 workspaces: 9,900 each require 1 unit of peak database capacity, and 100 each require 100 units. Total modeled peak demand is 19,900 units. The largest 1% account for roughly half. These are invented exercise inputs, not observed SaaS usage.

Suppose a shard safely supports 2,000 measured units, and you reserve 25% for recovery and moves. Its planning budget is 1,500 units, giving a demand-only floor of 14 shards after rounding up. That floor assumes the workload peaks coincide and the units are additive; validate both assumptions before treating it as a deployment count.

Now ask whether CPU, storage, connections, or a single hot index actually binds. Place using the limiting resource, not tenant count alone. If the interviewer reduces the workload, simplify the architecture.

For economics, propose comparing dedicated infrastructure plus fleet operations against pooled infrastructure plus isolation, instrumentation, and migration work. Attach measured costs later. Explain which customer requirement justifies the premium and what evidence would trigger a move. Connect this to your capacity-planning interview answer, without turning the discussion into an unsupported pricing estimate.

Define a proposed move trigger using sustained resource pressure and a forecast, then include a cooldown to prevent repeated relocations. Check destination headroom during both copying and normal operation. Assign the platform team responsibility for placement policy and the storage owner responsibility for migration correctness. A placement recommendation should not execute a move until its preconditions hold.

8. Move a tenant with a cutover proof

Draw a state machine: active on source, copying, catching up, fenced, active on destination, cleanup pending. Give every transition a precondition and an owner. The protocol below is a proposed interview design; provider replication features are ingredients, not proof that the complete move is safe.

Copy while the source remains authoritative

Inventory tables, objects, indexes, pending jobs, and idempotency records. Provision the destination’s schema and policies before loading data. Use a snapshot and change stream with a documented common position, preventing a gap between the initial copy and ongoing changes.

PostgreSQL 16 supports per-table replication row filters. For UPDATE and DELETE, filter columns must be covered by replica identity; filters do not restrict TRUNCATE. Verify every participating table and publication rather than assuming a tenant filter applies everywhere.

Plan schema and identifier handling separately. PostgreSQL logical replication does not replicate DDL or sequence state. A destination with copied rows may still need schema synchronization and safe sequence values before accepting writes.

Fence, validate, switch

Pause new tenant mutations and drain or abort in-flight source transactions. Establish the source write fence, then capture the final committed position. Require the destination to apply through that position. The fence and ordinary writes must share an enforcement mechanism that prevents a transaction from racing past the boundary.

PostgreSQL exposes subscription worker state, but a worker’s presence alone is not your cutover criterion. Check applied progress and data completeness. AWS DMS validation compares source and target rows and consumes extra resources; reserve capacity for the equivalent validation in your design.

Compare tenant-scoped counts, content checksums, object manifests, and business invariants at a stable boundary. Atomically publish destination placement with a higher epoch, enable destination writes, and invalidate routing caches. Keep source writes fenced. A stale worker must resolve fresh placement or fail safely.

Negotiate the write-pause budget before choosing this protocol. For the exercise, suppose the customer accepts a short maintenance window: pause writes while allowing explicitly bounded reads from the source, and present a retryable response for mutations. If continuous writes are mandatory, say that the design needs a more complex ownership-transfer protocol. Do not promise zero downtime while retaining an unexplained interval in which neither placement accepts work.

Rollback after writes is a data operation

Before destination writes begin, rollback can preserve the source as authority. Afterward, the source is stale. To return, fence the destination, transfer its accepted writes back, validate through a new boundary, and advance the epoch again. Otherwise choose forward repair. Keep rollback credentials, audit records, and retention time explicit; “flip the pointer back” is insufficient.

9. Include deletion, export, and restore in isolation

Propose an offboarding workflow that first blocks new work, then removes tenant data from each inventoried store. Record separate statuses for active data, derived indexes, exports, and retained backups. Explain retention with the interviewer’s requirements rather than promising immediate universal erasure.

Object versions are a concrete trap. A simple S3 DELETE in a versioned bucket creates a delete marker, leaving prior versions. NoncurrentVersionExpiration targets those noncurrent versions, with documented exceptions such as Object Lock. A missing object in the UI is not deletion evidence.

For exports, propose a tenant-scoped manifest, checksums, authorization at download time, and an expiration policy. For restore, rebuild into an isolated staging location, reconcile deletion records, validate ownership, and explicitly activate the result. Otherwise your recovery procedure could undo offboarding. Assign an operator and completion evidence to each lifecycle transition.

Consider deletion arriving during a move. In this proposed design, a single lifecycle coordinator serializes those transitions: suspend the move, keep both copies inaccessible, and include both locations in the deletion inventory. Record the final outcome before releasing the operation. The customer-facing status should distinguish access disabled from deletion verified and from retained backup expiry.

10. Rehearse a 45-minute design conversation

Use this recommended practice schedule and adapt it to the interviewer’s prompts:

  1. Minutes 0–5: Define the tenant, membership rules, threat model, residency, and failure objectives. Write the ownership and single-writer invariants.
  2. Minutes 5–12: Choose resource-level tenancy models and draw the directory, routing path, and enforcement points.
  3. Minutes 12–22: Trace a request and export job. Explain RLS roles, cache keys, object credentials, and duplicate handling.
  4. Minutes 22–32: Defend placement with hypothetical demand and walk through a tenant move.
  5. Minutes 32–40: Answer stale-routing, rollback-after-write, deletion, and restore follow-ups.
  6. Minutes 40–45: State the tradeoff, unresolved assumptions, validation plan, and next implementation step.

Three answers to practice aloud

“Why not give everyone a database?” “I can, if the requirement justifies it. I’ll compare fleet-management work and idle capacity, retain pooled application checks, and use the same directory abstraction for dedicated and shared storage.”

“What if the routing cache is stale?” “The old placement rejects writes after fencing. Requests refresh their mapping; background operations keep a stable idempotency key. Cache expiration supports convergence, while storage enforcement protects correctness.”

“What would you build first?” “Validated tenant context, restricted storage roles, cross-tenant negative tests, and a directory with lifecycle states. I’d rehearse a move on representative data before promising automated relocation.”

Record your practice answer in Interview Copilot’s system design mode and use question predictions to vary the follow-ups. Pair it with the database-migration playbook when cutover is your weakest area. Aim for an explanation another engineer can implement and challenge.

A useful multi-tenant design makes identity stable while placement changes. Finish your interview by following one customer’s document across a request, a job, a move, and a restore. At each boundary, say who authorizes access, who can write, and what evidence establishes completion.

Practice the follow-up that changes your design

Use Interview Copilot to rehearse tenant isolation, placement decisions, and safe migration answers with focused system design questions.

Create a free account