Compare
Stratum + MySQL
The world's most popular open-source relational database
MySQL is the default database for millions of applications, from WordPress to Laravel to legacy enterprise systems. @stratum-hq/mysql brings Stratum's tenant isolation to MySQL with three strategies: shared table (WHERE tenant_id filtering), table-per-tenant (separate tables per tenant), and database-per-tenant (full database isolation). The control plane (tenant hierarchy, config inheritance, audit log) remains in PostgreSQL via @stratum-hq/lib. MySQL carries your application data, scoped per tenant through structured query methods or ORM integrations.
Feature comparison
| Capability | MySQL | Stratum |
|---|---|---|
| Isolation strategies | Manual WHERE tenant_id on every query | 3 strategies: shared table, table-per-tenant, database-per-tenant |
| Tenant scoping | Application-level only | Structured methods auto-inject tenant_id into all queries |
| View-based isolation | Manual CREATE VIEW with session variables | Built-in createTenantView() with session variable management |
| Config inheritance | Not available | Built-in via PostgreSQL control plane |
| GDPR purge | Build it yourself | purgeTenantData() for all 3 strategies |
| ORM support | TypeORM, Knex, Sequelize (manual tenant logic) | TypeORM subscriber, Knex helper, Sequelize adapter included |
| Control plane | None | PostgreSQL via @stratum-hq/lib (tenant hierarchy, config, audit) |
| Security enforcement | Application-level (no RLS in MySQL) | Application-level for shared/table; DB-level for database-per-tenant |
Getting started
mysql-with-stratum.ts
import mysql from "mysql2/promise"; import { Stratum } from "@stratum-hq/lib"; import { MysqlSharedAdapter } from "@stratum-hq/mysql"; // Control plane: tenant hierarchy lives in PostgreSQL const stratum = new Stratum({ pool }); await stratum.initialize(); // MySQL adapter for application data isolation const mysqlPool = mysql.createPool(process.env.MYSQL_URL); const adapter = new MysqlSharedAdapter({ pool: mysqlPool, databaseName: "myapp", }); // Tenant created in PG control plane const tenant = await stratum.createTenant({ name: "Acme", slug: "acme" }); // Scoped queries auto-inject tenant_id const users = await adapter.scopedSelect(tenant.id, "users"); // only returns this tenant's rows
Things to know
- MySQL has no Row-Level Security. Isolation is enforced at the application layer via structured query methods. Use database-per-tenant for sensitive data requiring physical separation.
- MySQL Views referencing session variables (@stratum_tenant_id) may not use indexes efficiently. Benchmark with large tables. The shared-table adapter's structured methods are the high-performance path.
- The control plane (tenant hierarchy, config, audit log) always requires PostgreSQL via @stratum-hq/lib. MySQL carries application data only.
- Database-per-tenant requires a connection pool per tenant. Configure maxPools to avoid exhausting MySQL connections. Idle pools are automatically closed after 60 seconds.
- The TypeORM subscriber handles writes only (auto-injects tenant_id on insert). Use the shared-table adapter for tenant-scoped reads.
Start building with MySQL + Stratum
npm install @stratum-hq/lib pg