Documentation > Architecture > Multi-Tenancy

Multi-Tenancy Architecture

How SysManage isolates many tenants on one deployment — a control plane plus a dedicated database per tenant — and how that powers the Enterprise SaaS edition.

Isolation by separation, not by column

Most multi-tenant products put every customer's rows in one shared database and filter by a tenant_id column. SysManage does the opposite: each tenant gets its own physically separate PostgreSQL database. A missing WHERE tenant_id = ? can never leak one customer's data to another, because the data was never in the same database to begin with. Multi-tenancy is opt-in and licensed (the Enterprise SaaS tier); when it is disabled, SysManage runs as an ordinary single-database server.

The two topologies

The same SysManage codebase runs in two shapes. The diagram below contrasts the classic single-tenant deployment (Community, Professional, and on-prem Enterprise) with the multi-tenant topology behind Enterprise SaaS.

SysManage database topology: single-tenant (one server, one database) versus multi-tenant (control plane plus one isolated database per tenant, with OpenBAO brokering per-tenant credentials)

Click the diagram to open the full-size version in a new tab.

Single-tenant

One SysManage server talks to one PostgreSQL database. Hosts, users, inventory, and audit all live together. This is the Community Edition and the on-prem Professional and Enterprise deployments, and it is the only topology an air-gapped appliance ever uses.

Default Nothing about multi-tenancy is active unless you turn it on.

Multi-tenant

A control plane fronts many tenants. Control-plane metadata lives in a registry database; each tenant's operational data lives in its own database. The server resolves the caller to their tenant and routes every query to that tenant's database. OpenBAO brokers a short-lived, least-privilege credential per tenant.

Enterprise SaaS Licensed and enabled per deployment.

Control plane and tenant silos

A multi-tenant deployment is split into a small control plane and any number of tenant silos:

Control plane

The control plane is the SysManage server itself plus the licensed multitenancy_engine. It owns the tenant registry — which tenants exist and which database each one is placed in — and it is the only component that decides, per request, which tenant database to use. It also holds the small amount of genuinely cross-tenant state: the catalog of tenants and their placements.

Tenant silos

Each tenant is a silo: its own database, reached with its own credentials. A tenant silo contains everything host-scoped — hosts, packages, hardware inventory, compliance results, the agent message queue, and the tenant's own audit-relevant operational data. One tenant can never see another tenant's silo because it never holds a connection to it.

Database partitioning

SysManage organizes tables into three partitions, distinguished by table-name prefix, so it is unambiguous at the schema level where each table belongs:

PartitionPrefixLives inHolds
Registryregistry_*Control plane (registry DB)The tenant catalog and per-tenant database placements.
Sharedshared_*Control plane (shared DB)Canonical reference data that is identical for every tenant (for example the CVE/NVD catalog).
Tenant(unprefixed)Each tenant's databaseAll host-scoped operational data — one copy per tenant.

No cross-partition foreign keys

Because the partitions can live in physically separate databases, a foreign key can never point across a partition boundary — PostgreSQL cannot enforce a constraint into another database. Where a logical reference is needed across partitions (for example a row that records which server-global user created it), SysManage stores a soft reference: the GUID is kept, but no database-level foreign key is declared. This keeps each database self-contained and independently migratable.

Three migration chains

Each partition has its own Alembic migration chain — registry, shared, and tenant — with separate version tables. The registry and shared chains run once against the control-plane databases; the tenant chain is applied to every tenant database. Schema is open-source and identical for all tenants; only the routing logic that decides which database to touch is licensed.

Request routing

Routing is the heart of the data plane. Every request carries an active tenant — established from the authenticated session and JWT — and a single routing seam turns that into the right database connection:

  • User requests. Middleware binds the active tenant for the request; data-plane endpoints resolve their database session from it, so a tenant user only ever reads and writes their own database.
  • Server-wide background work. Jobs that must touch every host — the heartbeat sweep, the store-and-forward queue processors, the repository-mirror and upgrade-profile schedulers — fan out across the bootstrap database and every provisioned tenant database, one isolated session each.
  • Agent traffic. Agent reports flow through a durable, per-tenant message queue. Each inbound message is resolved to its host's tenant and written into that tenant's database; a bound host's data always lands in its own silo.

Fail loud, never guess

If the router cannot resolve a tenant for a piece of work, it logs loudly with full context and stops — it never silently falls back to a default database. Misrouting tenant data is treated as a correctness bug, not something to paper over.

The identity boundary

Not everything is per-tenant. SysManage draws a deliberate line:

Server-global (control plane)Per-tenant (silo)
User accounts, authentication, roles/RBAC, MFA, password-reset and external-IdP state, the tenant registry, licensing. Hosts and their inventory, packages, compliance results, the agent message queue, and the tenant's operational data.

Login is not per-tenant — a person authenticates once against the server — but the moment they act on managed data, that data is served from the active tenant's database. Keeping identity server-global while keeping managed data per-tenant is what lets one operator administer many tenants without ever mixing their fleets.

Binding a host to a tenant

A host belongs to exactly one tenant, decided at registration. An operator issues a tenant-scoped enrollment token from the control-plane UI and drops it into that host's agent configuration. When the agent registers, the server validates and consumes the token and records the host→tenant binding in the registry. From then on the agent is oblivious to tenancy: it just reports, and the server routes its data to the right silo. See the multi-tenant security and deployment guides for the operator workflow.

Provisioning and credentials

New tenants can be provisioned self-service from the control-plane UI. A least-privilege provisioner identity creates the tenant's database and registers it — the server never holds database-superuser rights. At run time, the tenant's database credentials are brokered by OpenBAO: short-lived, dynamically issued, and scoped to a single tenant. The full security treatment — why this design is hard to attack — is covered in the Multi-Tenant Security guide.

Opt-in and licensing

Multi-tenancy is entirely opt-in. With it disabled, none of the routing, registry, or per-tenant machinery is active and SysManage behaves exactly like the single-tenant topology — the same code, the same one database. The multi-tenant routing engine is part of the licensed Enterprise SaaS tier (MULTITENANT_SAAS); the database schema and partitioning themselves remain open-source. Without the licensed engine, a deployment configured for multi-tenancy fails loudly with a clear licensing error rather than misrouting.

Related documentation

🔐 Multi-Tenant Security

Why per-database isolation, OpenBAO-brokered credentials, and the identity boundary make this design exceptionally hard to attack.

Security treatment →

🚀 Enterprise SaaS

The multi-tenant, hosted edition: what it includes, who it is for, and how it compares to Community, Professional, and Enterprise.

Enterprise SaaS edition →

⚙️ Deployment

Standing up a multi-tenant deployment: the registry and tenant databases, OpenBAO, the three migration chains, and provisioning.

Deploy multi-tenancy →

🗄️ Database Design

The underlying schema, entity relationships, and persistence patterns that the partitions are built on.

Database design →