Drop-in multi-tenancy for Node.js — tenant hierarchy, config inheritance, permissions, audit, and GDPR in one library.
Stratum gives you hierarchical multi-tenancy with config inheritance, permission delegation, three isolation strategies (RLS, schema-per-tenant, database-per-tenant), field-level encryption, audit logging, GDPR compliance, and multi-region support. Built for B2B SaaS, MSSP/MSP architectures, and any product that needs nested tenant boundaries.
Every SaaS team starts with tenant_id on every table. It works — until it doesn't:
- Month 6: Enterprise customer needs custom config → hand-rolled config tables with no inheritance
- Month 12: Compliance audit → scramble to add audit logging, data export, purge capabilities
- Month 18: Large customer demands data isolation → painful migration from shared tables to schema-per-tenant
Stratum gives you all of this from day one. Start with flat tenancy, grow into hierarchy, config inheritance, permissions, and isolation strategies as your product matures.
npm install @stratum-hq/lib pgimport { Pool } from "pg";
import { Stratum } from "@stratum-hq/lib";
const stratum = new Stratum({ pool: new Pool(), autoMigrate: true });
await stratum.initialize();
const org = await stratum.createOrganization({ name: "Acme Corp", slug: "acme" });
await stratum.setConfig(org.id, "seat_limit", { value: 25 });
const config = await stratum.resolveConfig(org.id);
console.log(config.seat_limit.value); // 25That's it. autoMigrate: true creates all tables on first run — no CLI, no migrations, no Docker required (just a PostgreSQL connection string).
When you're ready for parent/child tenants, config inheritance, and permission delegation:
const msp = await stratum.createTenant({ name: "NorthStar MSP", slug: "northstar" });
const customer = await stratum.createTenant({ name: "Acme Corp", slug: "acme", parent_id: msp.id });
// Config flows root → leaf — children inherit automatically
await stratum.setConfig(msp.id, "max_seats", { value: 500, locked: true });
const config = await stratum.resolveConfig(customer.id);
// → { max_seats: { value: 500, inherited: true, locked: true } }# Scaffold a new project (recommended)
npx @stratum-hq/create my-app
# Or add to an existing project
npm install @stratum-hq/lib pg
# HTTP SDK with Express/Fastify middleware
npm install @stratum-hq/sdk
# NestJS integration (guard, decorator, module)
npm install @stratum-hq/nestjs
# Hono middleware
npm install @stratum-hq/hono
# MongoDB tenant isolation
npm install @stratum-hq/mongodb mongodb
# MySQL tenant isolation
npm install @stratum-hq/mysql mysql2
# React admin components
npm install @stratum-hq/react
# CLI tools
npm install -g @stratum-hq/cli| Package | What it does |
|---|---|
@stratum-hq/core |
Shared types, Zod schemas, error classes |
@stratum-hq/lib |
Direct library — tenants, config, permissions, ABAC, audit, GDPR |
@stratum-hq/control-plane |
Fastify v5 REST API with auth, scopes, OTel, Redis rate limiting |
@stratum-hq/sdk |
HTTP client with LRU cache, Express/Fastify middleware |
@stratum-hq/db-adapters |
PostgreSQL adapters — raw pg, Prisma, Sequelize, Drizzle, RLS, schema/DB isolation |
@stratum-hq/mongodb |
MongoDB tenant isolation — shared collection, collection-per-tenant, database-per-tenant |
@stratum-hq/mysql |
MySQL tenant isolation — shared table, table-per-tenant, database-per-tenant, TypeORM/Knex/Sequelize integrations |
@stratum-hq/react |
React components — tenant tree, config editor, permission editor |
@stratum-hq/cli |
CLI — init, migrate, scaffold, doctor |
@stratum-hq/nestjs |
NestJS integration — guard, @Tenant() decorator, module with DI |
@stratum-hq/hono |
Hono middleware — tenant extraction, ALS context |
@stratum-hq/test-utils |
Cross-tenant isolation test helpers |
@stratum-hq/create |
Project scaffolding — npx @stratum-hq/create my-app |
- Tenant hierarchy — tree structure with ltree, advisory locks, max depth 20
- Config inheritance — values flow root→leaf, parents can lock keys
- Permission delegation — LOCKED / INHERITED / DELEGATED modes with cascade revocation
- ABAC — attribute-based access control with 9 operators, hierarchical policy inheritance, deny-overrides-allow
- Three PostgreSQL isolation strategies — shared RLS, schema-per-tenant, database-per-tenant
- MongoDB isolation — shared collection, collection-per-tenant, database-per-tenant with Mongoose plugin
- MySQL isolation — shared table, table-per-tenant, database-per-tenant with TypeORM, Knex, and Sequelize integrations
- Field-level encryption — AES-256-GCM with key rotation
- Audit logging — every mutation with actor identity and before/after state
- GDPR compliance — data export (Article 20) and hard purge (Article 17)
- Webhooks — lifecycle events with HMAC signatures, retry, DLQ
- RBAC — scoped API keys (read/write/admin) with role assignments
- Multi-region — region CRUD with tenant migration
- OpenTelemetry — optional distributed tracing (zero overhead when disabled)
- Redis rate limiting — per-key sliding window, fail-open when Redis unavailable
- Config diff — compare resolved config between any two tenants
- Tenant impersonation — resolve full context for admin tooling
- Design system — CSS custom properties, dark mode, i18n, Storybook
- 1700+ unit tests + 20 integration tests — validated against real PostgreSQL 16, MongoDB 7, and MySQL 8
docker compose --profile demo up --build| Service | URL |
|---|---|
| Dashboard | http://localhost:3300 |
| API | http://localhost:3001 |
| Swagger | http://localhost:3001/api/docs |
Full docs are available via the Starlight docs site:
cd website && npm install && npm run devCovers: getting started, guides (hierarchy, config, permissions, isolation, API keys, webhooks, GDPR, multi-region), API reference, and per-package documentation.
npm install # Install dependencies
npm run build # Build all packages
npm test # Run unit tests
npx @stratum-hq/cli doctor # Check your DB setupIntegration tests run against real PostgreSQL, MongoDB, and MySQL:
docker compose --profile test up -d test-db
cd packages/integration-tests
DATABASE_URL=postgresql://stratum_test:stratum_test@localhost:5433/stratum_test \
npx vitest run| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
JWT_SECRET |
JWT signing secret (required in production) |
STRATUM_ENCRYPTION_KEY |
AES-256-GCM key for field encryption |
REDIS_URL |
Optional — enables distributed rate limiting |
STRATUM_API_KEY_HMAC_SECRET |
HMAC secret for API key hashing |
See the docs site for the full list.
@stratum-hq/lib (direct) ←→ @stratum-hq/control-plane (HTTP)
│ │
├── @stratum-hq/db-adapters ├── @stratum-hq/sdk
│ (pg, Prisma, Sequelize, │ (client, middleware)
│ Drizzle) │
│ ├── @stratum-hq/nestjs
├── @stratum-hq/mongodb │ (guard, decorator, DI)
│ (shared, collection, │
│ database isolation) ├── @stratum-hq/hono
│ │ (middleware, ALS context)
├── @stratum-hq/mysql │
│ (shared, table, database ├── @stratum-hq/react
│ isolation + ORM helpers) │ (UI components)
│ │
├── PostgreSQL 16 │
│ (ltree, RLS, AES) │
│ │
├── MongoDB 6/7 │
│ │
└── MySQL 8 │
└── @stratum-hq/cli
(init, doctor, migrate)
MIT
