Bulk Operations in MongoDB
So you've learned about individual inserts, updates, and deletes. But what happens when you need to do a lot of them at once? Sending hundreds of individual operations to the database is slow—it's like making a hundred separate trips to the grocery store instead of one big shopping trip. Bulk operations let you batch everything together for much better performance.
MongoDB's bulkWrite() method lets you combine multiple insert, update, and delete operations into a single database call. Instead of round-tripping to the database for each operation, you send them all at once and get back a single result. This is especially important for applications that need to process large amounts of data.
Think of bulk operations like a conveyor belt at a factory. Instead of moving each item individually, you load them all onto the belt and they process in one go. The time savings can be massive—sometimes 10x or more faster than individual operations.
Using bulkWrite()
bulkWrite() takes an array of operations, where each operation has a type (insertOne, updateOne, updateMany, deleteOne, or deleteMany) and the relevant data. You can mix different operation types in the same bulk call, which is incredibly flexible.
The method returns a result object that tells you how many documents were inserted, updated, and deleted. It also gives you any write errors that occurred, so you can handle failures gracefully. This is your go-to method for batch processing in MongoDB.
db.users.bulkWrite([
{ insertOne: { document: { name: "User1", email: "user1@test.com" } } },
{ insertOne: { document: { name: "User2", email: "user2@test.com" } } },
{ updateOne: { filter: { name: "Alice" }, update: { $set: { age: 30 } } } },
{ deleteOne: { filter: { name: "OldUser" } } }
])
Try it Yourself →
Ordered vs Unordered Operations
Here's an important distinction: ordered vs unordered bulk operations. Ordered operations stop at the first error. If operation 5 out of 10 fails, operations 6-10 never run. Unordered operations continue regardless of errors—if operation 5 fails, operations 6-10 still execute.
Use ordered operations when the order matters or when later operations depend on earlier ones. Use unordered operations when you want to maximize throughput and don't care about partial failures. Unordered operations can also be executed in parallel by MongoDB, making them faster for independent operations.
db.users.bulkWrite([
{ insertOne: { document: { name: "User1" } } },
{ insertOne: { document: { name: "User2" } } }
], { ordered: false })
db.users.bulkWrite([
{ updateOne: { filter: { name: "Alice" }, update: { $inc: { age: 1 } } } },
{ updateOne: { filter: { name: "Bob" }, update: { $inc: { age: 1 } } } }
], { ordered: true })
Try it Yourself →
Performance Considerations
Bulk operations are faster because they reduce network round-trips. Instead of sending 100 individual commands, you send one. This cuts down on latency and overhead, especially in applications where the database is on a different server. It's like sending one email with 100 lines instead of 100 separate emails.
There are limits to how many operations you can include in a single bulkWrite()—MongoDB caps it at 100,000 operations. For most use cases, this is plenty. If you need more, break your operations into chunks. Also, bulk operations use more memory, so be mindful of how large each batch is.
const operations = []
for (let i = 0; i < 1000; i++) {
operations.push({
insertOne: { document: { name: `User${i}`, index: i } }
})
}
db.users.bulkWrite(operations, { ordered: false })
Try it Yourself →
When to Use Bulk Operations
You should use bulk operations when importing large datasets, migrating data between collections, processing batch jobs, or syncing data from external sources. If you're doing more than a handful of operations, bulk is almost always the right choice.
Don't use bulk operations for real-time, single-document operations though. If you're just updating one user's profile, use updateOne()—it's simpler and more readable. Bulk operations add complexity, so only reach for them when the performance benefit matters. Balance is key.
db.products.bulkWrite([
{ updateMany: { filter: { category: "electronics" }, update: { $inc: { price: 1.05 } } } },
{ deleteMany: { filter: { stock: { $lte: 0 } } } },
{ insertOne: { document: { name: "New Product", price: 99.99, stock: 100 } } }
])
Try it Yourself →