250K
connections for a database per tenant
Even 5 per database × 50,000 tenants: over a terabyte of RAM, mostly for free tenants who log in twice a week. Pooled: 6,000.
Where does tenant isolation live?
Bad: App code only
Every query adds WHERE tenant_id. One forgotten filter in a new report leaks.
Good: Row-level security too
The database checks every row against a per-transaction tenant setting.
A request names acme.helpdesk.example. But anyone can type a host name.
The trick
The host only routes. The JWT’s signed tid must name the same tenant, or the gateway returns 403.
One verified tenant, stamped on every store
Shared code, not product code, adds it everywhere — a transaction setting, a cache-key prefix, a queue header, a log field.
A pooled cell fails. Who notices?
Only its 2,500 tenants, about 5%. Releases go cell by cell too, so a bad build meets a canary cell first and enterprise cells last.
40 min
SLA reminders wait behind one tenant’s import
In one FIFO, one tenant’s 200,000 import jobs take 2,500 s on 8 workers at 0.1 s a job. Give each tenant its own queue.
Move a 300 GB tenant live
- Copy a snapshot, ≈ 50 minutes
- Catch up by CDC, lag under 1 s
- Verify, freeze writes ≈ 10 s, flip the directory
- Replicate back 7 days; rollback is a flip
Remember
Pool by default, silo where it pays. Prove the tenant once, let the database enforce it, and keep failures in one cell.