How to fix BSONObjectTooLarge: object to insert too large in MongoDB

MongoDBINTERMEDIATEMEDIUMUpdated Dec 22, 2025ยท 173 views

MongoDB has a 16MB limit for individual BSON documents. This error occurs when trying to insert or update a document that exceeds this size limit. Common causes include storing large binary data, deeply nested objects, or accumulating too much data in arrays.

Quick fix

Fixes BSONObjectTooLarge: object to insert too large

// Node.js example with MongoDB driver
const { MongoClient, BSON } = require('mongodb');

async function checkDocumentSize(document) {
  // Calculate BSON size
  const size = BSON.calculateObjectSize(document);
  console.log(`Document size: ${size} bytes`);

  if (size > 16 * 1024 * 1024) { // 16MB in bytes
    console.error('Document exceeds 16MB limit!');
    return false;
  }
  return true;
}

// Or using the driver's built-in check
const client = new MongoClient(uri);
const collection = client.db('mydb').collection('mycollection');

try {
  await collection.insertOne(largeDocument);
} catch (error) {
  if (error.message.includes('BSONObjectTooLarge')) {
    console.log('Document too large - implement size check');
  }
}
  1. Check your document size before insertion
  2. Use GridFS for large binary data
  3. Normalize your data structure
  4. Implement data pagination for arrays
mongodb โ€” error
// Node.js example with MongoDB driver
const { MongoClient, BSON } = require('mongodb');
async function checkDocumentSize(document) {
// Calculate BSON size
const size = BSON.calculateObjectSize(document);
console.log(`Document size: ${size} bytes`);
if (size > 16 * 1024 * 1024) { // 16MB in bytes
console.error('Document exceeds 16MB limit!');
return false;
}
return true;
}
// Or using the driver's built-in check
const client = new MongoClient(uri);
const collection = client.db('mydb').collection('mycollection');
try {
await collection.insertOne(largeDocument);
} catch (error) {
if (error.message.includes('BSONObjectTooLarge')) {
console.log('Document too large - implement size check');
}
}
BSONObjectTooLarge: object to insert too large

What this error means

The "BSONObjectTooLarge: object to insert too large" error occurs when MongoDB rejects a document insertion or update because the document exceeds MongoDB's maximum BSON document size of 16 megabytes (16,777,216 bytes). BSON (Binary JSON) is the binary-encoded serialization format MongoDB uses to store documents. This limit exists because: 1. Larger documents consume more memory during processing 2. They increase network transfer times 3. They impact query performance and indexing efficiency 4. They affect replication and sharding operations When you encounter this error, MongoDB is protecting your database from performance degradation by enforcing this architectural limit. The error typically appears during insert(), update(), or save() operations when the serialized size of your document exceeds the limit.

Typical symptoms

  • Insert or update operations fail with "BSONObjectTooLarge: object to insert too large"
  • Database operations that previously worked start failing as data grows
  • Application crashes or throws exceptions when saving large documents
  • Batch operations fail when individual documents exceed the size limit
  • Aggregation pipeline stages fail due to large intermediate documents

Common causes

  1. Storing large binary data (images, files, PDFs) directly in documents
  2. Accumulating unlimited data in arrays without cleanup
  3. Deeply nested document structures with many levels of embedding
  4. Document fields containing very long strings or JSON blobs
  5. Aggregation operations creating large intermediate documents
  6. Using MongoDB as a file storage system instead of GridFS

How to fix "BSONObjectTooLarge: object to insert too large"

1Check your document size before insertion

Use MongoDB drivers or utilities to check document size before attempting to insert:

javascript
// Node.js example with MongoDB driver
const { MongoClient, BSON } = require('mongodb');

async function checkDocumentSize(document) {
  // Calculate BSON size
  const size = BSON.calculateObjectSize(document);
  console.log(`Document size: ${size} bytes`);

  if (size > 16 * 1024 * 1024) { // 16MB in bytes
    console.error('Document exceeds 16MB limit!');
    return false;
  }
  return true;
}

// Or using the driver's built-in check
const client = new MongoClient(uri);
const collection = client.db('mydb').collection('mycollection');

try {
  await collection.insertOne(largeDocument);
} catch (error) {
  if (error.message.includes('BSONObjectTooLarge')) {
    console.log('Document too large - implement size check');
  }
}
2Use GridFS for large binary data

For files, images, or binary data larger than 16MB, use MongoDB GridFS instead of storing directly in documents:

javascript
const { MongoClient } = require('mongodb');
const fs = require('fs');

async function storeLargeFile() {
  const client = new MongoClient(uri);
  const db = client.db('mydb');

  // Create GridFS bucket
  const bucket = new GridFSBucket(db, { bucketName: 'files' });

  // Upload large file
  const readStream = fs.createReadStream('large-video.mp4');
  const uploadStream = bucket.openUploadStream('large-video.mp4');

  readStream.pipe(uploadStream);

  uploadStream.on('error', (error) => {
    console.error('Upload failed:', error);
  });

  uploadStream.on('finish', () => {
    console.log('File uploaded successfully with ID:', uploadStream.id);
    // Store only the file reference in your document
    const document = {
      title: 'Video metadata',
      fileId: uploadStream.id,
      uploadedAt: new Date()
    };

    // This document will be small and within limits
    await db.collection('videos').insertOne(document);
  });
}
3Normalize your data structure

Break large documents into smaller, related documents using references:

javascript
// Instead of one huge document:
// BAD: Single document with unlimited array
const badDocument = {
  userId: '123',
  activities: [/* thousands of activity objects */],
  // ... other fields
};

// GOOD: Separate collections with references
const userDocument = {
  userId: '123',
  profile: { /* user profile data */ },
  // Keep only recent activities or summary
  recentActivities: [/* last 100 activities */],
  totalActivities: 1500
};

// Activities in separate collection
const activityDocument = {
  userId: '123',
  activityType: 'login',
  timestamp: new Date(),
  details: { /* activity details */ }
};

// Query with joins when needed
const activities = await db.collection('activities')
  .find({ userId: '123' })
  .sort({ timestamp: -1 })
  .limit(100)
  .toArray();
4Implement data pagination for arrays

For documents with growing arrays, implement pagination or archival:

javascript
// Strategy 1: Paginate array data
const paginatedDocument = {
  userId: '123',
  // Store array in chunks
  messagesPage1: [/* messages 1-100 */],
  messagesPage2: [/* messages 101-200 */],
  currentPage: 2,
  totalMessages: 250
};

// Strategy 2: Archive old data
async function archiveOldMessages(userId) {
  const user = await db.collection('users').findOne({ userId });

  if (user.messages.length > 1000) {
    // Move old messages to archive collection
    const oldMessages = user.messages.slice(0, 500);
    await db.collection('messageArchive').insertOne({
      userId,
      messages: oldMessages,
      archivedAt: new Date()
    });

    // Keep only recent messages
    await db.collection('users').updateOne(
      { userId },
      { $set: { messages: user.messages.slice(500) } }
    );
  }
}

// Strategy 3: Use capped arrays
const schema = {
  userId: String,
  // Keep only last 1000 messages
  recentMessages: {
    type: [MessageSchema],
    maxCount: 1000
  }
};
5Optimize aggregation pipeline stages

When aggregation pipelines create large intermediate documents, break them into stages:

javascript
// Problematic: Single stage creating huge document
const badPipeline = [
  {
    $group: {
      _id: '$userId',
      allData: { $push: '$$ROOT' } // Pushes entire documents
    }
  }
];

// Better: Process in stages with limits
const optimizedPipeline = [
  // Stage 1: Filter and project only needed fields
  {
    $match: { timestamp: { $gte: startDate } }
  },
  {
    $project: {
      userId: 1,
      importantField: 1,
      // Don't include large fields
      largeBinaryField: 0
    }
  },

  // Stage 2: Group with aggregation, not array accumulation
  {
    $group: {
      _id: '$userId',
      count: { $sum: 1 },
      total: { $sum: '$amount' },
      // Use $addToSet for unique values instead of $push for all
      uniqueItems: { $addToSet: '$itemId' }
    }
  },

  // Stage 3: Add pagination with $skip and $limit
  { $skip: 0 },
  { $limit: 100 }
];

// For very large aggregations, consider:
// 1. Using $facet for parallel processing
// 2. Implementing map-reduce for distributed processing
// 3. Using $out to write intermediate results
6Monitor and prevent size issues proactively

Implement monitoring to catch size issues before they cause errors:

javascript
// Regular document size checks
async function monitorDocumentSizes() {
  const collections = await db.listCollections().toArray();

  for (const collInfo of collections) {
    const collection = db.collection(collInfo.name);

    // Sample documents to check sizes
    const sample = await collection.find().limit(10).toArray();

    sample.forEach((doc, index) => {
      const size = JSON.stringify(doc).length;
      if (size > 10 * 1024 * 1024) { // Warn at 10MB
        console.warn(`Large document in ${collInfo.name}: ${size} bytes`);
      }
    });

    // Check for documents approaching limit
    const largeDocs = await collection.aggregate([
      {
        $addFields: {
          docSize: { $bsonSize: '$$ROOT' }
        }
      },
      {
        $match: {
          docSize: { $gt: 15 * 1024 * 1024 } // > 15MB
        }
      }
    ]).toArray();

    if (largeDocs.length > 0) {
      console.error(`Found ${largeDocs.length} documents approaching 16MB limit in ${collInfo.name}`);
    }
  }
}

// Set up alerts
const alertThreshold = 15 * 1024 * 1024; // 15MB
if (documentSize > alertThreshold) {
  sendAlert('Document approaching BSON size limit', {
    collection: collectionName,
    documentId: doc._id,
    size: documentSize
  });
}

Advanced notes

## Understanding BSON Size Calculation

The 16MB limit applies to the serialized BSON size, not the JavaScript object size. Key factors affecting BSON size:

1. Field names: Each field name is stored as a string in BSON
- { "veryLongFieldNameThatTakesSpace": value } uses more space than { "v": value }

2. Data types: Some types have overhead:
- ObjectId: 12 bytes
- Date: 8 bytes
- Binary data: length + subtype + bytes
- Arrays: Additional array overhead

3. Nesting overhead: Each nested document adds BSON document overhead

## GridFS vs External Storage

While GridFS solves the 16MB limit by chunking files, consider:
- GridFS: Good for files up to 16GB, integrated with MongoDB, supports range queries
- External storage (S3, Azure Blob): Better for very large files, cheaper storage, CDN integration

## Sharding Considerations

For sharded collections:
- The 16MB limit applies per document, not per shard
- Large documents can't be split across shards
- Consider sharding key selection for documents that might grow large

## Compression Options

MongoDB 4.2+ supports snappy and zlib compression:
- Reduces storage size but not BSON limit
- Network transmission uses compressed BSON
- Enable with storage.wiredTiger.collectionConfig.blockCompressor

## Migration Strategies

If you have existing documents near or exceeding the limit:
1. Use $out aggregation to rewrite with normalized structure
2. Implement gradual migration during low-traffic periods
3. Use change streams to migrate documents as they're updated

## Related Errors
- DocumentTooLarge: Similar error in some MongoDB drivers
- QueryExceededMemoryLimitNoDiskUseAllowed: Aggregation memory limits
- TransactionTooLarge: Transaction operation size limits

Frequently asked questions

What does "BSONObjectTooLarge: object to insert too large" mean?
The "BSONObjectTooLarge: object to insert too large" error occurs when MongoDB rejects a document insertion or update because the document exceeds MongoDB's maximum BSON document size of 16 megabytes (16,777,216 bytes). BSON (Binary JSON) is the binary-encoded serialization format MongoDB uses to store documents. This limit exists because: 1.
How do I fix "BSONObjectTooLarge: object to insert too large"?
MongoDB has a 16MB limit for individual BSON documents. This error occurs when trying to insert or update a document that exceeds this size limit. Common causes include storing large binary data, deeply nested objects, or accumulating too much data in arrays.
What causes "BSONObjectTooLarge: object to insert too large"?
Storing large binary data (images, files, PDFs) directly in documents Accumulating unlimited data in arrays without cleanup Deeply nested document structures with many levels of embedding
Is the "BSONObjectTooLarge: object to insert too large" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading