MongoDB Limitations & Restrictions

Understanding MongoDB's technical boundaries and constraints

< class="article-body">

⚠️ MongoDB Limitations

MongoDB has technical limitations on document size, nesting depth, collection names, and query complexity. Understanding these boundaries helps you design efficient database schemas and avoid errors. These limits ensure optimal performance and prevent resource exhaustion in production environments.


// Document size limit: 16MB
db.collection.insertOne({
  data: "..." // Must be under 16MB
})
                                    

Key Limitation Categories

📄

Document Size

Maximum document limits

16MB max BSON format
🔢

Nesting Depth

Document structure limits

100 levels Nested docs
📛

Naming Limits

Database and collection names

64 chars DB 120 bytes col
🔍

Query Limits

Query operation constraints

Sort memory Index keys

🔹 Document Size Limit (16MB)

Each MongoDB document has a maximum size of 16 megabytes in BSON format. This limit prevents excessive memory usage and ensures efficient document handling. For large data like images or videos, use GridFS or store files externally and keep only references in documents.

// ❌ PROBLEM - Document too large
db.posts.insertOne({
  title: "My Post",
  content: "...", // Very long text
  images: [
    { data: "base64..." }, // Large image data
    { data: "base64..." }, // Another large image
    // ... many more images
  ]
  // Total size > 16MB = ERROR
})

// ✅ SOLUTION 1 - Store references instead
db.posts.insertOne({
  title: "My Post",
  content: "Article text...",
  images: [
    { url: "https://cdn.example.com/img1.jpg" },
    { url: "https://cdn.example.com/img2.jpg" }
  ]
})

// ✅ SOLUTION 2 - Use GridFS for large files
const bucket = new GridFSBucket(db)
const uploadStream = bucket.openUploadStream('large-file.pdf')
fs.createReadStream('./file.pdf').pipe(uploadStream)

// Store reference in document
db.posts.insertOne({
  title: "My Post",
  fileId: uploadStream.id
})

Result:

✅ Documents stay under 16MB limit

✅ Large files stored separately

✅ Efficient document operations

🔹 Nesting Depth Limit (100 Levels)

MongoDB allows a maximum of 100 levels of nested documents. Deeply nested structures can impact query performance and make data harder to work with. For complex hierarchies, consider flattening your structure or using references to separate collections instead of deep nesting.

// ❌ PROBLEM - Too deeply nested (approaching 100 levels)
db.data.insertOne({
  level1: {
    level2: {
      level3: {
        // ... 97 more levels
        level100: {
          value: "data"
        }
      }
    }
  }
})

// ✅ SOLUTION 1 - Flatten structure
db.data.insertOne({
  level1_value: "data",
  level2_value: "data",
  level3_value: "data",
  final_value: "data"
})

// ✅ SOLUTION 2 - Use references
db.categories.insertOne({
  _id: "cat1",
  name: "Electronics",
  parentId: null
})

db.categories.insertOne({
  _id: "cat2",
  name: "Computers",
  parentId: "cat1"
})

db.categories.insertOne({
  _id: "cat3",
  name: "Laptops",
  parentId: "cat2"
})

Result:

✅ Structure stays within limits

✅ Better query performance

✅ Easier to maintain and update

🔹 Namespace Length Limit

The full namespace (database name + collection name) cannot exceed 120 bytes. This includes the dot separator between database and collection names. Choose concise, descriptive names to stay within this limit while maintaining clarity about what data each collection contains.

// Namespace = database.collection
// Maximum: 120 bytes total

// ❌ PROBLEM - Namespace too long
use myVeryLongDatabaseNameForProduction
db.myVeryLongCollectionNameWithLotsOfDetails.insertOne({})
// Total: 70+ bytes - might exceed limit with full path

// ✅ SOLUTION - Use shorter names
use prodDB
db.users.insertOne({ name: "John" })
db.orders.insertOne({ total: 100 })
db.products.insertOne({ title: "Widget" })

// Check namespace length
const namespace = "prodDB.users"
console.log(namespace.length) // 12 bytes - well within limit

// ✅ Good naming practices
use appDB
db.user_profiles.insertOne({})    // Clear and concise
db.order_items.insertOne({})      // Descriptive
db.product_reviews.insertOne({})  // Understandable

Result:

✅ Namespaces within 120 byte limit

✅ Clear, readable names

✅ No length errors

🔹 Index Limitations

MongoDB indexes have several important limits: maximum 64 indexes per collection, compound indexes limited to 32 fields, and index key size cannot exceed 1024 bytes. These limits ensure indexes remain efficient. Design your indexes carefully to stay within these boundaries while optimizing query performance.

// Index Limits:
// - Max 64 indexes per collection
// - Max 32 fields in compound index
// - Max 1024 bytes for index key

// ❌ PROBLEM - Too many fields in compound index
db.users.createIndex({
  field1: 1, field2: 1, field3: 1,
  // ... 30 more fields
  field33: 1  // ERROR: Exceeds 32 field limit
})

// ✅ SOLUTION - Create focused indexes
db.users.createIndex({ email: 1 })
db.users.createIndex({ lastName: 1, firstName: 1 })
db.users.createIndex({ age: 1, city: 1 })

// ❌ PROBLEM - Index key too large
db.articles.createIndex({ 
  fullText: 1  // If fullText > 1024 bytes, error
})

// ✅ SOLUTION - Use text index for large text
db.articles.createIndex({ 
  fullText: "text"  // Text index handles large content
})

// List all indexes
db.users.getIndexes()

// Drop unused indexes to stay under 64 limit
db.users.dropIndex("oldIndex_1")

Result:

✅ Indexes within all limits

✅ Optimized query performance

✅ Efficient index usage

🔹 Sort Memory Limit (32MB)

MongoDB allocates a maximum of 32MB of memory for sort operations without an index. If your sort operation exceeds this limit, you'll get an error. The solution is to create an index on the fields you're sorting by, which allows MongoDB to sort efficiently without loading all data into memory.

// ❌ PROBLEM - Sort without index on large dataset
db.products.find().sort({ price: 1 })
// If result set > 32MB, ERROR: 
// "Executor error during find command: 
//  OperationFailed: Sort operation used more than 
//  the maximum 33554432 bytes of RAM"

// ✅ SOLUTION 1 - Create index for sort field
db.products.createIndex({ price: 1 })
db.products.find().sort({ price: 1 })
// Now sorts efficiently using index

// ✅ SOLUTION 2 - Limit results
db.products.find()
  .sort({ price: 1 })
  .limit(100)  // Reduce data to sort

// ✅ SOLUTION 3 - Use allowDiskUse (aggregation only)
db.products.aggregate([
  { $sort: { price: 1 } }
], { allowDiskUse: true })

// Check if index exists
db.products.getIndexes()

Result:

✅ Sort operations complete successfully

✅ Memory usage stays under 32MB

✅ Fast query performance

🔹 Array Element Limits

While MongoDB doesn't have a hard limit on array size, very large arrays can cause performance issues and approach the 16MB document limit. For arrays with thousands of elements, consider using separate collections with references or pagination to maintain good performance and stay within document size constraints.

// ⚠️ PROBLEM - Very large array in document
db.users.insertOne({
  name: "John",
  posts: [
    { id: 1, title: "Post 1", content: "..." },
    { id: 2, title: "Post 2", content: "..." },
    // ... thousands more posts
    // Approaches 16MB limit, slow queries
  ]
})

// ✅ SOLUTION 1 - Separate collection with reference
db.users.insertOne({
  _id: "user123",
  name: "John"
})

db.posts.insertMany([
  { userId: "user123", title: "Post 1", content: "..." },
  { userId: "user123", title: "Post 2", content: "..." },
  // Can have unlimited posts
])

// Query user's posts
db.posts.find({ userId: "user123" })

// ✅ SOLUTION 2 - Keep small arrays only
db.users.insertOne({
  name: "John",
  recentPosts: [  // Only last 10 posts
    { id: 1, title: "Latest Post" },
    { id: 2, title: "Second Latest" }
  ],
  totalPosts: 1500  // Just count
})

Result:

✅ Documents stay under size limit

✅ Fast query performance

✅ Scalable data structure