Skip to main content
Architecture · for engineers

How a multi-tenant SaaS platform is built: Fleet, your platform stack and your apps

Fleet is the service that provisions each customer's infrastructure. The Control Plane is the service where operators set plans, settings and tenant allocation. Tenant allocation means which parts of a customer's stack, such as database and compute, are shared or dedicated. Implementation details for engineering evaluation: layered services, published protocols, per-organization and per-instance storage, tier-aware database scaling and an SDK for platform integration on AWS.

Elastic by design

Scale any layer without touching the rest

Stateless services, per-job worker fleets and service-owned databases give the platform independent scaling dials, vertical and horizontal, at every layer on AWS Fargate and EC2.

Per servicePer workerPer database

Load balancer

per-service routing

task 1task 2task 3task 4task 5task 6

measured load

capacity follows

The stack

Technologies your engineers already operate

The platform uses Python and TypeScript services with PostgreSQL, Redis, Kafka and S3 on AWS. Shared libraries apply the same authentication, configuration and telemetry contracts across services.

Backends

Python + FastAPI services, one per capability, behind a shared base library (models, CRUD, auth, rate limiting, tracing).

Frontends

React + TypeScript, one component library and one config bootstrap shared across every app and the customer portal.

Data

PostgreSQL per application instance for app data and per organization for platform services, with managed connection pooling and, on Large and Extra Large deployment tiers, Aurora readers; Redis for cache and tokens; Kafka for events; S3 for objects.

Cloud

AWS only — managed RDS, S3 and KMS, provisioned for each client. Customer data can be placed in the region it belongs to, including the EU.

Staged deployment

Every client stack is deployed in four ordered stages

Fleet builds each stack as code from one reviewed deployment file, one stage at a time. Each stage uses only the recorded outputs of the stage before it, and every apply follows a refreshed preview whose change set must match what was approved.

  1. 01

    Network

    The private network for the stack: isolated subnets, outbound gateway and base firewall rules.

  2. 02

    Shared infrastructure

    The PostgreSQL cluster, Redis, Kafka and object storage that every service in the stack uses.

  3. 03

    Service data and secrets

    A database, encryption keys and credentials for each service, created inside the shared infrastructure.

  4. 04

    Services and edge

    The running services and their release pipelines, the web frontends and public DNS.

Deployments run from inside the stack's private network. Operators preview each change, approve the exact resources it will touch, and the platform reads the result back after it is applied. A change that touches a data store requires a fresh snapshot first.

Partial by design

Bound a deployment at any stage. A network-and-data environment with no services is a supported shape, and a real apply refuses to reach below a stage that is already complete.

Account and size per environment

Each environment names its AWS region and runs in its own account, for development, staging, recovery or a specific client. The deployment file carries the sizing, so two environments differ by their file.

Pause, resume, tear down

Pause scales services to zero and stops the database; resume restores what pause recorded. Teardown snapshots the database first, keeps the state store and signed images, and is safe to re-run.

Read how deployment on demand works →

Configuration model

The Control Plane supplies typed configuration to each service

Services read typed configuration from the Control Plane. Operators also compose plans from application features, quotas and supported AWS resource allocations, including customer-specific plans and organization overrides.

Typed sections

Settings are typed sections written whole, for example PUT /config/auth. Unknown fields are rejected.

The narrowest value wins

Settings can be set for the platform, a region, an organization, an app instance or a single user, with the narrowest value winning. Unset sections fall back to platform defaults.

Custom plans combine features, quotas and infrastructure

Create a plan for one customer, set feature and quota values, attach pooled or dedicated AWS resources, and assign it without changing product code.

Plan upgrades can change the isolation boundary

Offer a shared-to-dedicated database, compute or observability upgrade, or place the tenant on an isolated stack. The Control Plane tracks eligible component migrations while Fleet provisions the target AWS resources.

Published interfaces

Standard protocols define external integration

The platform uses OIDC, OAuth, SAML, LDAP, SCIM, CloudEvents and OpenTelemetry so existing identity, event and observability tools can connect through documented contracts.

OIDC + OAuth 2.0

The OpenID Connect provider implements authorization-code flow with PKCE, publishes signing keys and rotates refresh tokens.

CloudEvents v1.0

Every platform event is a CNCF CloudEvents envelope on Kafka — one canonical wire format, no bespoke event shapes.

OpenTelemetry

Traces, metrics and structured logs across every service; one trace ID follows a request end to end.

SCIM 2.0

Enterprise identity providers (Okta, Microsoft Entra ID, OneLogin) provision users and groups directly.

Signed webhooks

HMAC-SHA256 per-subscriber signatures, exponential retry, dead-letter — verifiable on the receiver.

JSON Schema-validated app manifests

Each app declares its platform integrations in versioned YAML, validated against JSON Schema on publish.

Tenant isolation and scaling

Storage placement and request scope enforce tenant isolation

Customer data in Authorization, Audit, Comments, Support, AI and sign-in accounts is kept in a separate database for each organization. Data and Automation use a separate database for each app instance. Notification delivery is planned to follow. Shared services scope customer queries by organization and app instance. Every customer starts on shared infrastructure; supported components can move to infrastructure provisioned for that customer alone, sold as a plan upgrade, with the application code unchanged.

Pooled by default

Most tenants share infrastructure with strict per-query scoping, which is cheaper and simpler to operate.

Erasure by contract

Apps declare export and erasure endpoints, and the Control Plane tracks the cascade across installed apps.

Services scale with load

Customer-facing services start with two tasks by default. ECS target tracking on CPU and memory adds capacity up to the configured maximum and removes it back to the floor.

Database read capacity

Managed connection pools absorb session spikes. On the Large deployment tier one Aurora reader is added and on Extra Large two, while transactions and consistent reads stay on the writer.

Dedicated resources by plan

  1. 01

    Offer it per component

    Each app lists which of its components can run dedicated: database, compute, cache, event topics, sign-in issuer, storage encryption and monitoring. Each keeps a shared default.

  2. 02

    Put it on a plan

    In the Control Plane, choose shared or dedicated for each component of a plan and set its size. Price the plan like any other and publish it.

  3. 03

    Provisioned on subscribe or upgrade

    When a customer subscribes or upgrades, the platform builds their dedicated components and points the app at them. Eligible running components move with tracked migration, cutover and rollback.

Customer-managed keys require a dedicated database. How to define a dedicated resource.

Review the request path and isolation boundaries

A solution architect will walk your team through the request path, the tenancy model and the isolation boundaries against the SaaS you are building.