Thank you @minha for your answer, it’s very important, now I’m little bit closer to shared collection pattern.
If sharding is not an option, the best approach depends on the number of tenants and data volume per tenant. Here’s a breakdown of the options without sharding:
Shared Database, Shared Collection (One Collection for All Tenants)
All tenants share a single collection, distinguished by tenantId
.
Example Structure
db.orders.insertOne({ tenantId: "tenant1", userId: "user123", orderId: 1, item: "Laptop" });
db.orders.insertOne({ tenantId: "tenant2", userId: "user456", orderId: 2, item: "Phone" });
Pros
Simple management – No need to create collections dynamically.
Efficient indexing – One index works for all tenants:
db.orders.createIndex({ tenantId: 1, userId: 1 });
Good for a smaller number of tenants (up to a few thousand) with moderate data per tenant.
Cons
Performance issues at very large data volumes – Queries can slow down if the collection grows to hundreds of millions of documents.
No strict data isolation – All tenants share the same collection.
When to choose?
If you have fewer than 1,000 tenants and a moderate amount of data per tenant (up to tens of millions of records).
Shared Database, Separate Collections (Each Tenant Has Its Own Collection, Shared DB)
Each tenant has its own collection, e.g., orders_tenant1
, orders_tenant2
.
Example Structure
db.orders_tenant1.insertOne({ userId: "user123", orderId: 1, item: "Laptop" });
db.orders_tenant2.insertOne({ userId: "user456", orderId: 2, item: "Phone" });
Pros
Better data isolation – No risk of one tenant affecting another’s data.
Faster queries for a single tenant – MongoDB scans a smaller collection.
Cons
Scalability issues with a high number of tenants – Managing thousands of collections can be inefficient.
Higher memory usage – Each collection requires its own indexes.
When to choose?
If you have 1,000 – 10,000 tenants, and each has a significant amount of data.
Separate Database per Tenant (Each Tenant Has Its Own Database)
Each tenant has a completely separate database, e.g., tenant1_db
, tenant2_db
.
Example Structure
use tenant1_db;
db.orders.insertOne({ userId: "user123", orderId: 1, item: "Laptop" });
use tenant2_db;
db.orders.insertOne({ userId: "user456", orderId: 2, item: "Phone" });
Pros
Best data isolation – No shared indexes or risks of cross-tenant access.
Easier backup and archival – Each database can be managed separately.
Cons
Not scalable for a large number of tenants – Managing 10,000+ databases is impractical.
Hard to scale without sharding – Each database has its own size limitations.
When to choose?
If you have fewer than 1,000 tenants, but each has a very large dataset (100+ million records).
Summary: Which Solution is Best Without Sharding?
Number of Tenants |
Data per Tenant |
Best Approach |
< 1,000 |
Small/Medium |
Shared Collection |
1,000 – 10,000 |
Large Data Volume |
Separate Collections |
> 10,000 |
Extremely Large Data |
Difficult without sharding, sharding recommended |
If sharding is not an option and you have a high number of tenants (>10,000) or large data volumes per tenant, scaling will be challenging.
If possible, Shared Collection remains the most efficient solution as long as data volume does not exceed MongoDB’s collection limits (~terabytes). 
If sharding is not an option, the best choice depends on the number of tenants and data volume per tenant. Here’s a simple guide to help you decide:
Best Solution Without Sharding?
Number of Tenants |
Data per Tenant |
Best Approach |
< 1,000 |
Small/Medium |
Shared Collection (1 collection for all tenants) |
1,000 – 10,000 |
Large |
Separate Collections (1 collection per tenant) |
> 10,000 |
Very Large |
Difficult without sharding, consider sharding |
Recommended Solution for Most Cases → Shared Collection
If you have less than 10,000 tenants, the best option is a single shared collection where each document includes tenantId
.
Why?
Easier to manage – No need to create thousands of collections.
Efficient indexing – A single index can serve multiple tenants.
Better query performance – MongoDB optimizes queries when properly indexed.
When to Avoid It?
If you have millions of records per tenant, queries might slow down without sharding.
When to Use Separate Collections?
If you have 1,000+ tenants and large data per tenant, separate collections (orders_tenant1
, orders_tenant2
, etc.) can improve performance.
Why?
Better query performance – Each query targets a smaller dataset.
More isolation – Each tenant’s data is in its own collection.
Downsides?
MongoDB struggles with too many collections (10,000+ collections can cause indexing issues).
When to Use Separate Databases?
If you have fewer than 1,000 tenants but each has a huge dataset (100M+ records), separate databases (tenant1_db
, tenant2_db
) offer full isolation.
Why?
Best for high-volume tenants – No shared indexes, better scalability.
Easier backup and archiving – Each tenant can be managed separately.
Downsides?
Not scalable beyond 1,000 tenants – Managing thousands of databases is impractical.
Final Answer
If you have <10,000 tenants → Use Shared Collection (Best for performance & management).
If you have large data per tenant (100M+ records per tenant) → Use Separate Collections.
If you have very few but extremely large tenants → Use Separate Databases.
Without sharding, Shared Collection is the best balance between simplicity and scalability.
Given your setup (<1000 tenants, ~50 dynamic forms per tenant), the best approach without sharding is Shared Collection.
Why?
Efficient Indexing – A single collection with indexes on tenantId
and formId
will keep queries fast.
Easier Management – No need to create and maintain thousands of collections.
Scalable Enough – As long as individual forms don’t store massive amounts of data, performance will remain good.
Recommended Schema
db.forms.insertOne({
tenantId: "tenant1",
formId: "form123",
name: "Customer Feedback",
fields: [{ label: "Name", type: "text" }, { label: "Rating", type: "number" }]
});
Indexing Strategy
db.forms.createIndex({ tenantId: 1, formId: 1 });
This ensures fast lookups per tenant while keeping index memory usage low.
Would you like optimizations for specific queries? 