Single-tenant DB-per-client: what we gain vs what we sacrifice
The most visible architectural decision of Suite HUB: each client has their own database. Here the real trade-offs, not the textbook ones.
When we started Suite HUB in 2024, the first big architectural decision was: single-tenant DB-per-client or shared multi-tenant. We chose single-tenant, and two years later I still think it was the right decision — but with real costs it is honest to recognize.
The context
Our typical client is a Panamanian SMB: an auto shop, a laundromat, a restaurant, a veterinary clinic. Sizes of 1–5 locations, 3–30 users, manageable data volumes (tens of thousands of transactions/year, not millions).
For that segment, the question is not “how do I scale to 10 million tenants?” but “how do I deliver a reliable system with the least possible risk?”.
What we decided
One database per client installation. Each client has:
- Their own SQLite DB (HUB Lite/Core) or MySQL (HUB Pro)
- Their own folder on the server with their
config.php - Their own domain or subdomain
- Their own set of users, modules, configuration
Multi-location lives inside the tenant, not as a shared tenant. A client with 3 locations has one DB with 3 locations as entities, not 3 separate DBs.
What we gain
1. Total security isolation
If a client is compromised, the others do not find out. Zero risk of a poorly filtered query exposing another tenant’s data. The attack surface for a multi-client catastrophe is virtually zero.
This is huge for clients with sensitive data (medical, fiscal, financial).
2. Aggressive customization without cross-risk
Each installation can have custom modules, specific integrations, UI modifications, without affecting anyone else. When a client asks “I need an extra field on the invoice”, we add it without thinking twice.
In shared multi-tenant, that kind of custom forces feature flags, conditionals, a whole layer of complexity that accumulates.
3. Trivial backup, restore, migration
Restoring a client is copying a SQLite file or a MySQL dump. Migrating from one
server to another is scp + three config files. If a client wants their data for
legal audit, I hand them the .sqlite and they take it.
4. Predictable performance
Each client’s DB has its own cache, its own storage, its own indexes. A client with heavy queries does not degrade another. There is no “noisy neighbor”.
5. Simplified compliance
For DGI Panama (electronic invoicing), having each taxpayer’s data physically separated simplifies audits and certifications. The same would apply to HIPAA, GDPR, banking regulations.
What we sacrifice
1. “Mass update” operation is more complex
When a new version releases, it is not UPDATE to a DB — it is a script that
iterates through each installation, validates state, applies migration. We built an
auto-migration system that runs when each client starts, but it requires discipline.
2. Cross-analytics require extraction
I cannot run a query “show me the average of invoices/day from all my clients” on a single DB. Requires a job that extracts anonymized metrics from each tenant to a separate analytics DB. More infrastructure.
3. Higher cost per client
Each installation consumes its slice of RAM, disk, connections. For an SMB of 5 users that is negligible, but for a hypothetical account with 10,000 clients our stack would not scale linearly as shared multi-tenant would.
4. More involved onboarding
Creating a new client is not INSERT INTO tenants — it is DB provisioning, config,
domain, first admin user. We have a script that automates it, but it is still more
complex than self-service signup.
Why I would still choose the same
For the segment we serve, the benefits weigh more:
- Small team → fewer things can break everyone
- Clients with sensitive data → isolation is value
- Customization is competitive advantage → multi-tenant would complicate it
- Modest target volume (hundreds, not thousands) → the extra cost is assumable
If I were building a B2C consumer SaaS with 100K free users, of course I would go multi-tenant. But that is not what we are.
When we do pivot
For HUB Enterprise (future, for chains / franchises with dozens of locations), we are evaluating a hybrid: shared multi-tenant with strict logical partitioning, because chain logic requires native consolidation that single-tenant complicates.
But that is a different edition, not a change of the base architecture.
Conclusion
“Single-tenant vs multi-tenant” is not a universal technical decision — it is a business model decision. Know your client, know your volume, know your team. The right choice is the one that lets you sleep peacefully and move fast on what matters, not the one that looks better on a whiteboard architecture.
Comments
Comments via GitHub Discussions — requires GitHub login.