Technical Guide

AWS Serverless Multi-Tenant SaaS: Architecture That Scales Per Tenant

A technical guide to building multi-tenant SaaS on AWS. Tenant isolation, serverless compute, per-tenant cost caps and rate limits, data residency, and infrastructure as code.

July 22, 202619 min readOronts Engineering Team

The Question That Defines Your Architecture

Let me be direct: the single decision that shapes a multi-tenant SaaS is how you isolate tenants. Get it right and you scale to thousands of customers on shared infrastructure with a clean cost model. Get it wrong and you either leak one customer's data to another, which ends the company, or you spin up dedicated infrastructure per tenant, which bankrupts it.

The answer is not "pick one isolation model." It is to apply isolation at every layer, so no single mistake exposes data across tenants. This is defense in depth applied to multi-tenancy, and it is the difference between a platform you can trust with enterprise data and a demo you cannot.

Multi-tenant isolation is not a feature you add. It is a property you enforce at every layer: the database, the search index, the API, the agents, and the dashboard. One layer is not enough.

We run this architecture in production in our own Exfinity platform, a multi-tenant SaaS on AWS serving isolated tenants from shared infrastructure in an EU region. This guide is the real design. For the container-orchestration alternative, see our Kubernetes for SaaS platforms guide, and this is core cloud work.

Who Cares About What

RoleThe real questionWhat good looks like
ArchitectHow is tenant data isolated?Enforcement at every layer, not one
Security leadCan one tenant reach another's data?No, by design, provable
CTODoes cost scale with customers, not servers?Shared infra, per-tenant metering
SRECan one tenant take down the platform?Per-tenant rate limits and cost caps
DPOWhere does the data physically live?A documented region, EU if required

Serverless Versus Containers: Pick Per Service

Serverless is not all-or-nothing. The right architecture uses both, chosen per workload.

Functions-as-a-service suit spiky, event-driven, short-lived work: an API endpoint, a queue consumer, a scheduled job. You pay per invocation and scale to zero. Long-running or stateful services, a search API holding warm indexes, an AI runtime managing agent state, suit containers on managed compute, where you keep processes warm and control the runtime.

WorkloadFitsWhy
API endpoints, webhooksFunctionsSpiky, short, scale to zero
Queue consumers, cronFunctionsEvent-driven, bounded runtime
Search, AI runtimeContainersWarm state, long-lived connections
Background processorsContainersSteady throughput, resource control

Exfinity runs its API and checkout flows as functions and its search, AI runtime, ingestion, and dashboard as containers on managed compute, each scaling independently. The lesson: do not force one model onto everything. Our platform engineering guide covers this trade-off in depth.

The Six Layers of Tenant Isolation

This is the core of the whole guide. Isolation is enforced at every layer a request touches.

Request with tenant identity
   │
   ▼
[1] API middleware   ── tenant id from the token, never the query string
[2] Database         ── tenant id as partition key on every query
[3] Search index     ── tenant filter on every search
[4] Agents / AI       ── conversation and memory scoped per tenant
[5] Tool layer       ── every tool checks scope before it runs
[6] Dashboard        ── cross-tenant access returns not-found, not forbidden

API middleware. The tenant identity comes from verified token claims, not from a query parameter a caller could forge. A tenant id in the URL from a non-admin is silently ignored. This is the first gate and the one people most often get wrong.

Database. Every query includes the tenant as a partition key. There is no code path that reads a table without a tenant scope. This is enforced in the data-access layer, not left to each caller to remember.

Search index. Every search carries a tenant filter, so one tenant's query can never return another's documents, even though they share an index.

Agents and memory. Each conversation is scoped to a single tenant, and agent memory recall enforces that scope, so an agent serving tenant A cannot recall tenant B's threads. We cover this in our agent memory guide.

Tool layer. Every tool an agent can call checks the tenant scope before executing, carrying the tenant, channel, and allowed resources in its runtime context.

Dashboard. Cross-tenant access returns a not-found rather than a forbidden, so the response does not even confirm that another tenant's resource exists.

Six layers, and a single missed check at one of them does not expose data, because the others still hold. That is the whole point of defense in depth. Our multi-tenant system design guide goes deeper on the patterns.

The AWS Building Blocks

Here is how the pieces map to concrete services, drawn from a production deployment.

ConcernServiceRole
Function computeLambdaAPI, checkout, queue consumers, cron
Container computeECS FargateSearch, AI runtime, ingestion, dashboard
Operational dataDynamoDBTenant-partitioned tables, pay-per-request
SearchOpenSearchText plus vector index, VPC-only
EventsKafka (MSK)Product ingestion stream
QueuesSQS (FIFO and standard)Ordered booking, notifications, webhooks
SchedulingEventBridgeCrawl schedules, freshness, cleanup
AuthCognitoUser pools, token enrichment with tenant claims
EdgeCloudFrontCDN for widgets and API caching
Object storageS3Vouchers, snapshots, audit archive
CacheElastiCache RedisQuery cache, rate limiting, locks
EmailSESTransactional email
SecretsSecrets ManagerProvider keys, connection strings, KMS-encrypted

The pattern to notice: data stores sit in private subnets with no public access, compute reaches them over the VPC, and only the load balancer and CDN face the internet. Token enrichment at the auth layer is where the tenant identity is stamped into every request, so downstream services can trust it. Our infrastructure as code guide covers provisioning all of this reproducibly.

Per-Tenant Limits: Stopping One Tenant From Sinking the Ship

Shared infrastructure means one tenant's runaway load or leaked key is everyone's problem, unless you bound it. Two controls matter.

Per-tenant rate limits cap request volume by tenant and by credential type, so a hot tenant cannot starve the rest. Per-tenant cost caps put a hard monthly ceiling on expensive operations, model calls especially, as a blast-radius backstop against a leaked key or a runaway agent loop. In Exfinity these caps are set well above a tier's expected usage, so they are a safety net, not a billing throttle, and hitting one returns a clear error for the rest of the month rather than silently overcharging.

ControlProtects againstBehavior
Per-tenant rate limitNoisy-neighbor loadThrottle with a clear retry signal
Per-tenant cost capLeaked keys, runaway loopsHard ceiling, clear error at the cap
Per-turn agent boundsA single request loopingCap steps, tool calls, output

Without these, your most careless customer sets the reliability floor for everyone. Our designing systems for failure guide covers this defensive posture.

The Event Backbone: Decoupling the Platform

A multi-tenant platform that does everything in the request path is fragile, because one slow dependency stalls the user. The services that scale well move work off the request path onto an asynchronous backbone, so the user gets a fast response and the heavy lifting happens out of band.

Two mechanisms carry this. Ordered queues handle work that must happen exactly once and in sequence, a booking that becomes a supplier reservation, with a dead-letter queue catching anything that fails so nothing is silently lost. A scheduling service fires recurring jobs, freshness checks, cleanup, archival, without a cron server to babysit.

User action ──▶ fast response
     │
     └──▶ ordered queue ──▶ worker ──(fail)──▶ dead-letter queue
                                                      │
                                            alert, inspect, replay

Exfinity runs booking and document generation through ordered queues with dead-letter queues, and drives its crawl and maintenance schedules from an event bus. A healthy platform keeps those dead-letter queues empty, so a non-empty one is an alert. This is the same reliability discipline as our enterprise integration guide, applied inside a single platform, and the general pattern is in our event-driven architecture guide.

Data Residency: Where It Physically Lives

For European customers, this is not a preference, it is a requirement. If your contract or the GDPR says data stays in the EU, your architecture has to enforce it, not just claim it.

That means choosing a region deliberately and keeping storage and processing inside it. Exfinity runs in an EU region, with all operational data, search, and caching in-region, and a documented list of sub-processors and what each one touches. Model providers outside the EU are handled as sub-processors with data-processing terms, and personal data can be kept out of them entirely with tokenization, as covered in our PII-safe RAG guide. Our GDPR and AI guide and trust page cover the compliance framing.

Infrastructure as Code: Reproducible or Nothing

A multi-tenant platform you cannot rebuild from code is a liability. Everything, networking, compute, data stores, IAM, is defined as code and applied through a pipeline, so environments are reproducible and changes are reviewed.

The discipline that matters: separate state per environment, least-privilege roles for the pipeline itself, and no manual console changes that drift from the code. Exfinity provisions its stack with Terraform and a wrapper for per-service configuration and remote state, promoting through development, staging, and production with manual approval on production. Our infrastructure as code guide covers the practices that keep this maintainable.

Getting Started

  1. Decide isolation first. Enforce tenant scope at every layer before you build features.
  2. Split compute by workload. Functions for spiky and event-driven, containers for warm and stateful.
  3. Stamp tenant identity at auth. Put it in verified token claims, never trust the client.
  4. Add per-tenant limits early. Rate limits and cost caps before you onboard real load.
  5. Codify everything. Infrastructure as code from day one, not retrofitted.

This is staged, and it fits the phased delivery in our methodology. Our cloud and consulting teams design and build these platforms. Start at contact or get a quote.

Common Ways This Goes Wrong

  1. Isolation at one layer. A single missed check leaks data. Enforce tenant scope everywhere.
  2. Trusting the client for tenant identity. A tenant id in the URL is forgeable. Use verified token claims.
  3. No per-tenant limits. One tenant's load or leaked key sinks everyone. Bound it.
  4. Public data stores. Databases and search must live in private subnets, reachable only over the VPC.
  5. Manual infrastructure. Console changes drift and cannot be rebuilt. Codify everything.
  6. Ignoring residency until a contract asks. Retrofitting region constraints is painful. Choose deliberately up front.

Who Builds This

Oronts is a founder-led software company in Munich. Refaat Al Ktifan, our founder and solution architect, leads a senior team across backend, cloud, and platform. The architecture in this guide is the real design behind Exfinity, a multi-tenant SaaS we run on AWS in an EU region. We design the isolation model, build the serverless and container layers, codify the infrastructure, and hand you a platform you can operate and scale. See our services and solutions pages.

Takeaways

  • The defining decision in multi-tenant SaaS is isolation, enforced at every layer, not just one.
  • Split compute by workload: functions for spiky and event-driven, containers for warm and stateful.
  • Stamp tenant identity at the auth layer from verified claims, and never trust the client for it.
  • Bound every tenant with rate limits and cost caps so one cannot sink the platform.
  • Choose your region deliberately for data residency, and codify all infrastructure.

Multi-tenancy done right is invisible to the customer and obvious in the architecture. Every layer knows whose data it is holding, and no single mistake can cross that line.

Building or scaling a multi-tenant platform on AWS? Tell us about your isolation and residency needs. Start at contact or get a scoped quote.

Topics covered

AWS multi-tenant SaaSserverless architecturetenant isolationECS FargateDynamoDBinfrastructure as codeTerraformmulti-tenant securitySaaS platformcloud architecture

Building something like this?

We design and ship production systems like the one in this guide. Talk to the engineers who wrote it, no sales pitch.

Start a conversation