Skip to content
Agencei
Reference architecture

B2B SaaS software vendors

Reference architecture: multi-tenant SaaS on AWS

This reference architecture describes a typical solution we implement. It does not correspond to an identified client.

Context

This reference architecture is not a client project: it is the foundation we use as a starting point when a software vendor asks us to design a B2B SaaS. It is maintained as a demonstrative project and serves as a basis for discussing technical choices.

The modelled case is a management application sold by subscription to companies, where each customer company (tenant) has its own users, data and settings while sharing the same infrastructure.

The goal is to show a proven way of answering the questions every SaaS vendor faces: how to isolate data, how to manage subscriptions, how to deploy without downtime and how to keep costs under control.

Problem

A multi-tenant SaaS must guarantee that no customer can see another customer's data, while sharing servers, database and deployments. Isolation errors are the most serious and the hardest to detect after the fact.

It must also tie billing to access rights (trial, plan, quotas, suspension) and be shippable several times a week without interrupting the service for every customer.

Constraints

  • Strict data isolation between tenants, verifiable through automated tests.
  • A single code base and a single infrastructure for all customers, to keep operating costs down.
  • Deployments without service interruption and simple rollback.
  • Infrastructure fully described as code and reproducible across several environments.
  • Billing provider abstraction so the business domain is not coupled to Stripe.

Architecture

The front end is a Next.js application served behind a CDN, with server-side rendering for public pages and a React application for the customer area.

The API is built in Java with Spring Boot; every request carries the tenant identifier extracted from the authentication token, propagated down to the data layer.

PostgreSQL on Amazon RDS hosts all data in a shared database; row-level security applies a per-tenant filter directly in the database, in addition to application-level checks.

Redis acts as cache, session store and queue for background jobs (email sending, exports, webhooks).

The API and front-end Docker containers are deployed on Amazon ECS; the whole stack (network, ECS, RDS, Redis, secrets, logs) is described in Terraform.

GitHub Actions builds the images, runs the tests (including tenant isolation tests), applies migrations and deploys blue/green.

Solution

The tenant identifier is the backbone of the architecture. It is set at authentication, carried in the context of every request and set as a PostgreSQL session variable; row-level security policies reject any read or write that does not match. A query that forgot the filter on the application side therefore returns nothing, rather than another customer's data.

Billing is modelled in the business domain (plans, subscriptions, trial periods, quotas) and an adapter translates these notions to Stripe. Payment webhooks are processed idempotently and update the tenant's access rights; switching provider means writing another adapter.

Database migrations are written to remain compatible with the previous API version, which enables blue/green deployment: the new version is started next to the old one, verified, then receives the traffic. Rolling back means switching the traffic back.

Observability is built in from the start: structured logs carrying the tenant identifier, per-tenant metrics, distributed traces and alerts on errors and latency. AWS costs are tagged per component so they can be tracked.

Outcome

  • Data isolation is enforced by both the database and the application, and verified by an automated test suite that deliberately attempts to access another tenant's data.
  • Deployments become reproducible: every environment is created from the same Terraform code and every version goes through the same pipeline.
  • Releases happen without downtime thanks to blue/green deployment and backward-compatible migrations.
  • Billing rules live in the business code and are tested independently of the payment provider.
  • Per-tenant logs and metrics make it possible to diagnose an issue reported by a customer without digging through all the traffic.

Improvements achieved

  • Offer a dedicated-database mode for customers requiring physical isolation, while keeping the same code base.
  • Add per-tenant SAML/OpenID Connect SSO for enterprise accounts.
  • Introduce progressive per-tenant (canary) deployments alongside blue/green.
  • Automate load tests in the pipeline to catch performance regressions.
  • Add tenant data export and full deletion to handle GDPR requests and cancellations.

Screenshots

Screenshots will be added once the project is published.

Tell us about your project

Describe your need in a few lines: we come back to you with a first analysis and the next steps.