Multi-Tenant SaaS Databases: Shared Database or One Database per Workspace?
- Published on
- Reading time
- 14 min read
Multi-tenancy is not just adding a tenant_id column. Shared tables, schema-per-tenant and database-per-workspace each change isolation, migrations, backups, analytics, connection pressure and operating cost. Here is how I evaluate the trade-offs before the architecture becomes expensive to change. #SaaS #MultiTenancy #DatabaseArchitecture #PostgreSQL #SoftwareArchitecture #Laravel #Golang
Multi-Tenant SaaS Databases: Shared Database or One Database per Workspace?
One of the earliest architecture decisions in a SaaS product can become one of the hardest to change later:
Where does each customer's data live?
The apparently simple answer is usually a shared database with a tenant_id or workspace_id column.
That can be exactly the right design.
But it is not the only design.
At the other end, every workspace can have its own database. Between them, there are models such as schema-per-tenant and hybrid approaches where most customers share infrastructure while selected tenants receive stronger isolation.
There is no universally correct choice.
The useful question is:
Which tenancy boundary matches the product's isolation requirements, operating model and expected scale?
The database topology is only one part of multi-tenancy. Authentication, authorization, queues, cache keys, object storage, search indexes, logs, background jobs and integrations must respect the same boundary.
The three common database models
A useful starting point is to separate three patterns.
1. Shared database, shared tables
All workspaces use the same database and tables. Rows contain a tenant identifier.
bookings
-------------------------
id
workspace_id
customer_id
status
...
This is operationally simple and often efficient.
One migration updates one schema. Cross-tenant analytics are straightforward. Connection management is predictable. Infrastructure overhead per customer is low.
But isolation depends heavily on application correctness.
A missing tenant condition in the wrong query can become a data-isolation incident.
2. Shared database, separate schemas
Customers share a database server but each has a separate schema or equivalent logical namespace.
This creates a stronger structural boundary than shared tables while avoiding a completely separate database server for every tenant.
It also introduces more operational work: schema migrations, provisioning and tooling must understand many schemas rather than one.
3. Database per workspace
Each workspace receives its own database.
Workspace A → Database A
Workspace B → Database B
Workspace C → Database C
The isolation boundary is easier to reason about because customer business data does not share the same database namespace.
But the operational problem changes dramatically.
You are no longer operating “a database.”
You are operating a fleet of databases.
That distinction matters.
Why teams consider database-per-workspace
The strongest argument is usually isolation, not performance.
If customer A and customer B live in different databases, many classes of accidental cross-tenant query become structurally harder.
That can also make some operational tasks cleaner.
A tenant-specific backup, restore, export or deletion can be easier to reason about when that tenant has a clear storage boundary.
Large customers may also have different retention, regional or operational requirements.
But stronger isolation is not free.
You pay for it in provisioning, migrations, connection management, observability and fleet operations.
Isolation is not automatically security
A separate database does not mean the SaaS is secure by default.
The application can still connect to the wrong database.
A queue job can still carry the wrong workspace context.
A cache key can still omit the tenant identifier.
An object-storage path can still expose another tenant's file.
An administrator tool can still bypass normal boundaries.
So database isolation should be treated as one layer of defense, not the entire multi-tenant security model.
A robust system makes workspace context explicit throughout the request and job lifecycle.
Shared tables are not automatically unsafe either
The opposite assumption is also wrong.
A well-designed shared-table system can enforce tenant scoping through application architecture, database policies where appropriate, automated tests and carefully designed access patterns.
For many SaaS products, this is the simplest architecture that satisfies the requirement.
Do not choose database-per-workspace merely because it sounds more “enterprise.”
Choose it because the isolation and operational properties solve a real requirement.
The hidden cost: provisioning
With a single shared database, onboarding a new workspace may be mostly application data.
With database-per-workspace, onboarding can become infrastructure orchestration.
A provisioning flow may need to:
- Create or allocate the database.
- Apply the current schema.
- Create credentials or access policy.
- Register the connection with the application.
- Seed required system data.
- Verify health.
- Record the workspace as ready only after provisioning succeeds.
That process needs to be idempotent.
If step four fails, retrying should not accidentally create a second database or leave an unknown half-provisioned tenant.
Provisioning becomes part of your product architecture.
Migrations become a distributed operation
This is one of the biggest differences.
In a shared database, a migration runs once.
With hundreds or thousands of workspace databases, the same logical migration may run hundreds or thousands of times.
Now ask:
- Can the migration be safely retried?
- What happens if 97% succeed and the rest fail?
- Can old and new application versions tolerate mixed schema versions temporarily?
- How do you know which tenants are behind?
- How quickly can you pause a bad rollout?
A migration command is no longer enough.
You need migration orchestration and migration state.
Never assume every tenant is on the same schema version
At fleet scale, partial failure is normal.
A database may be temporarily unavailable. A connection can time out. A migration may hit unexpected tenant-specific data.
Track schema state per workspace.
Then deployment tooling can answer:
Current application schema target: 142
Workspace A: 142 ✓
Workspace B: 142 ✓
Workspace C: 141 !
Workspace D: migration failed
That visibility is far more useful than assuming a deployment script completed because the process exited successfully.
Backups are where isolation can become valuable
Database-per-workspace can make tenant-level backup and restore conceptually clean.
If one customer needs recovery, you may be able to restore their database without restoring every other customer's business data.
But the system still needs answers for:
- Backup frequency.
- Retention.
- Encryption.
- Restore testing.
- Point-in-time recovery.
- Where backups are stored.
- How credentials are protected.
- How a restored database is reattached safely.
A backup that has never been restored in a test is only a theory.
Deleting a workspace becomes clearer — and more dangerous
A strong physical boundary can simplify deletion: identify the tenant's database and remove it according to retention policy.
It can also make a mistake catastrophic.
A wrong database identifier in a destructive operation is unacceptable.
Destructive lifecycle operations should require strong identity checks, audit logs, delayed deletion where appropriate and a clear recovery policy.
Isolation makes the unit of deletion obvious. It does not remove the need for safeguards.
Connection management can become the real bottleneck
This is easy to underestimate.
A traditional application may maintain a pool of connections to a small number of databases.
Database-per-workspace can create a much larger connection topology.
Opening and holding a dedicated pool for every tenant can consume resources long before query throughput becomes the problem.
The architecture may need dynamic connection resolution, bounded pools, connection proxies or other strategies depending on the database platform and workload.
This is particularly important for systems with many tenants but relatively low activity per tenant.
Do not size only for queries per second.
Size for active connection behavior too.
Tenant context must survive queues
A web request can identify the workspace from a domain, session, token or route.
A background job does not automatically have that request context.
If a job processes a report, sends a notification or synchronizes an integration, it must carry an explicit workspace identity and resolve the correct database before executing tenant work.
Conceptually:
Job payload
workspace_id
task data
↓
Workspace resolver
↓
Correct database connection
↓
Domain operation
Never depend on whatever tenant connection happened to be active in the worker previously.
Long-running workers make that mistake especially dangerous.
Cache is part of multi-tenancy
Suppose two workspaces both have a record with ID 42.
A cache key like:
property:42
is not tenant-safe.
The key needs the boundary:
workspace:abc:property:42
The same principle applies to locks, rate limits, sessions, computed reports and temporary data.
Database isolation does not protect a shared Redis namespace automatically.
Files and object storage need the same boundary
If customer files live in S3-compatible storage or another object store, define tenant-aware paths and authorization.
For example:
workspaces/{workspace_id}/documents/{document_id}
Do not assume an unguessable URL is an authorization mechanism.
The database model and file model should tell the same tenancy story.
Search indexes can reintroduce the isolation problem
A product may use separate databases but one shared search index.
Now the search layer becomes another place where tenant filtering must be correct.
The same applies to vector databases and RAG systems.
If AI retrieval searches across customer knowledge, workspace isolation must be enforced before or during retrieval, not merely mentioned in the prompt.
“Only answer using this customer's data” is not a security boundary.
Analytics are easier with shared data
This is an important trade-off.
A shared database naturally supports queries across tenants for internal product analytics.
Database-per-workspace fragments that data.
If the business needs platform-wide metrics, you may need a separate analytics pipeline that intentionally collects approved events or aggregates from tenant databases into an analytics store.
Do not solve this by giving every dashboard a loop that connects to every production tenant database in real time.
Operational databases and analytical workloads have different needs.
Reporting needs an explicit strategy
A report for one workspace is straightforward: query that workspace's database.
A platform-wide report is not.
Decide early which reports are:
- Tenant-local.
- Operational platform metrics.
- Financial aggregates.
- Product analytics.
Then create the appropriate data path for each.
Database-per-workspace is much easier to operate when cross-tenant analytics are designed intentionally rather than discovered later.
Observability must include the workspace
Logs such as:
SQL timeout
are not enough.
Operational telemetry should identify the relevant workspace safely, along with database/cluster, application version, schema version, job/request correlation and error context.
This allows you to answer whether a problem affects one tenant, a group of tenants or the whole platform.
Be careful not to leak sensitive tenant data into logs while adding this context.
Cost does not scale only with storage
The economic difference between tenancy models includes more than disk space.
Database-per-workspace may add costs for:
- Minimum database/server allocations.
- Connections/proxies.
- Backups.
- Monitoring.
- Provisioning systems.
- Migration orchestration.
- Operational support.
- Cross-tenant analytics pipelines.
A shared database may be cheaper operationally, especially early in a product's life.
The right comparison is total operating complexity and cost, not only database price per GB.
Database-per-workspace does not require server-per-workspace
These ideas are often confused.
A logical database per customer does not necessarily mean a dedicated physical database server for each customer.
Multiple tenant databases may share a managed database cluster or server depending on the platform and isolation requirements.
The important architecture question is the logical isolation boundary and how resources are allocated underneath it.
That distinction can significantly change the economics.
A hybrid model is often worth considering
The choice does not always need to be permanent and universal.
A SaaS might use shared infrastructure for standard customers while giving specific enterprise or regulated customers a dedicated database or cluster.
Another design might group tenants into shards, with many workspaces per database but fewer than one global database.
Hybrid architectures introduce routing complexity, but they can let infrastructure match customer requirements rather than forcing every tenant into the most expensive isolation level.
Think about tenant movement before you need it
If a customer starts in a shared environment and later needs dedicated isolation, can you move them?
If a cluster becomes full, can workspaces migrate elsewhere?
Useful architecture separates the tenant identity from the physical connection location.
Instead of assuming:
workspace_id → hard-coded database name
maintain a resolvable mapping:
workspace_id → placement → connection/configuration
That creates room for rebalancing and enterprise upgrades later.
Data residency can influence the topology
Some products eventually need to place customer data in a specific region.
A tenant placement layer can support this more naturally than a single global database, but residency requirements extend beyond the primary database.
Backups, files, search, logs, analytics and third-party integrations may also contain customer data.
Do not call a system region-isolated because only PostgreSQL moved.
Laravel: central database plus tenant connections
In a Laravel application, a common conceptual design is to keep platform-level data centrally:
Central DB
- workspaces
- users / memberships
- subscriptions
- tenant placement
- platform configuration
Then tenant business data lives behind a workspace-resolved connection.
Middleware can establish workspace context for HTTP requests, while queue middleware or job bootstrapping does the same for background work.
The important rule is that domain code should not manually invent connection names everywhere.
Centralize tenant resolution so it can be tested and audited.
Go: make tenant dependencies explicit
In Go, tenant resolution can be modeled explicitly through application dependencies.
A handler or worker resolves the workspace, obtains the appropriate data-store handle, then passes a tenant-scoped repository/service into the use case.
This helps avoid global mutable connection state.
The exact implementation depends on the database driver and topology, but the principle is durable:
Tenant identity should be an explicit dependency of tenant work.
Testing needs adversarial tenant cases
Happy-path tests are not enough.
For every important tenant-scoped operation, test questions such as:
- Can workspace A request workspace B's record ID?
- Can a queued job resolve the wrong tenant?
- Can a cached value cross tenant boundaries?
- Can search return another tenant's document?
- Can an administrator endpoint accidentally skip scoping?
- What happens when tenant provisioning is incomplete?
Multi-tenant bugs are often ordinary software bugs with unusually serious consequences.
Test the boundary deliberately.
When shared tables are usually the better choice
A shared database is often attractive when:
- The product is early and requirements are still changing.
- Tenant data volumes are modest.
- Cross-tenant analytics are important.
- There is no strong requirement for physical/logical database isolation.
- The team wants the simplest operational model.
- Application-level tenant scoping can be enforced reliably.
Simple is valuable.
Do not pay distributed-operations complexity before the product needs it.
When database-per-workspace becomes more attractive
It deserves serious consideration when:
- Stronger tenant isolation is a core requirement.
- Tenant-level backup/restore/export is important.
- Customers may require different placement or operational policies.
- Individual tenants can become large enough to need independent management.
- The engineering team is prepared to automate database fleet operations.
The final point matters most.
If provisioning, migration, monitoring and recovery are manual, database-per-workspace can become an operational trap.
A decision framework
Before choosing, write down the answers to these questions:
- What isolation does the product actually require?
- How many tenants do we expect, and how many are concurrently active?
- How large can one tenant become?
- Do we need tenant-level backup or restore?
- Do customers need region or infrastructure choices?
- How much cross-tenant analytics does the business require?
- Can our deployment system migrate many databases safely?
- How will workers resolve tenant context?
- How will we monitor schema version and health per tenant?
- What is the total operational cost of the topology?
- Can tenants move between placements later?
- Which other systems — cache, files, search, AI retrieval — must enforce the same boundary?
Those answers are more useful than copying the tenancy architecture of another SaaS.
The real architecture is the lifecycle
Creating the database is the easy part.
The real design includes:
Provision
→ Migrate
→ Connect
→ Observe
→ Back up
→ Restore
→ Upgrade
→ Move
→ Suspend
→ Delete
If you choose database-per-workspace, design that lifecycle before tenant count makes manual operations impossible.
If you choose shared tables, design and test tenant scoping before the codebase makes unscoped access normal.
Multi-tenancy is not a database feature. It is an application-wide isolation model.
The database topology should reinforce that model, not carry it alone.
Designing a SaaS product and deciding between shared multi-tenancy, database-per-workspace or a hybrid architecture?
I help teams design SaaS architecture from tenancy and data boundaries through APIs, queues, deployment, observability and production scaling — so the isolation model fits the business instead of becoming an expensive rewrite later.
Related: SaaS Development, SaaS vs Custom Software, Engineering Architecture and Building a Private RAG Stack on PostgreSQL.
Comments (0)