Five Common MongoDB Indexing Mistakes That Kill Performance

MongoDB Indexing Mistakes

Avoid MongoDB performance pitfalls by learning five common indexing mistakes that slow down your database. Includes CLI examples, charts, and actionable fixes.

Table of Contents

🔈Introduction

MongoDB is renowned for its flexibility and scalability as a NoSQL database, but when it comes to performance, indexing is everything. A well-designed index can make queries blazingly fast, while poor indexing can quietly strangle performance, bloat storage, and frustrate developers.

In this post, we’ll explore five common MongoDB indexing mistakes that hurt performance and scalability. We’ll look at the symptoms, why they happen, how to fix them, and show real examples with CLI commands and performance tips.


✅ 1. Not Creating Indexes on Frequently Queried Fields

🔍 The Mistake

One of the most basic yet common mistakes is failing to create indexes on fields used frequently in find(), sort(), update(), or aggregation queries. MongoDB will scan every document in a collection (a collection scan) if no appropriate index exists.

⚠️ Why It’s a Problem

  • Increases query time exponentially as data grows
  • Increases CPU load
  • Can block operations under high load

🛠️ How to Fix It

Use the createIndex() method to add indexes to fields that are regularly filtered, sorted, or joined on.

📌 Example

				
					db.users.createIndex({ email: 1 })
				
			

If you frequently search by email, this index makes those queries significantly faster.

📊 CLI Example

Check for slow queries using the MongoDB Atlas Performance Advisor or system profiler:

				
					db.system.profile.find({ millis: { $gt: 100 } }).sort({ ts: -1 }).limit(5)
				
			

✅ 2. Creating Too Many Indexes

🔍 The Mistake

Some developers try to solve all performance problems by adding more indexes. However, every write operation (insert, update, delete) must update every index, which introduces overhead.

⚠️ Why It’s a Problem

  • Slows down write operations
  • Increases storage usage
  • Can confuse the query planner

🛠️ How to Fix It

  • Audit existing indexes with db.collection.getIndexes()
  • Remove unused indexes:
				
					db.orders.find({ userId: 123, status: "delivered" })
				
			

📊 Cost of Index Overhead

Index CountWrite Latency ImpactStorage Increase
1–3Minimal~10%
4–6Noticeable~20–30%
7+High50%+
💡Actual values vary based on workload and index types.

🛠️ How to Fix It

  • Audit existing indexes with db.collection.getIndexes()
  • Remove unused indexes:
				
					db.collection.dropIndex("index_name")
				
			

Use $indexStats to see index usage:

				
					db.collection.aggregate([ { $indexStats: {} } ])
				
			

✅ 3. Not Using Compound Indexes for Multi-Field Queries

🔍 The Mistake

Relying on multiple single-field indexes instead of a compound index for multi-field queries causes MongoDB to perform index intersection, which is slower.

⚠️ Why It’s a Problem

  • lndex intersection isn’t as fast as a direct compound index
  • Query planner may choose suboptimal execution plans
  • Misses opportunities for efficient sort operations

🛠️ How to Fix It

Build compound indexes that reflect the structure of your most common queries.

📌 Query Examples

				
					db.orders.find({ userId: 123, status: "delivered" })
				
			

Recommended index:

				
					db.orders.createIndex({ userId: 1, status: 1 })
				
			

If sorting is involved:

				
					db.orders.find({ userId: 123 }).sort({ createdAt: -1 })
				
			

Use:

				
					db.orders.createIndex({ userId: 1, createdAt: -1 })
				
			

⚡ Pro Tip

Order of fields matters in compound indexes. Use the Equality → Sort → Range (ESR) rule:

  • Equality first (=),
  • Then sort (sort()),
  • Then range ($gt, $lt, etc.).

✅ 4. Ignoring Index Cardinality

🔍 The Mistake

Creating indexes on low-cardinality fields (e.g., status, gender, isActive) that don’t help filter documents meaningfully. MongoDB ends up scanning large portions of the collection anyway.

⚠️ Why It’s a Problem

  • Low selectivity reduces the usefulness of the index
  • Wastes resources and storage
  • Query planner may ignore the index

📊 Cardinality Breakdown

FieldTypeCardinalityUseful Index?
genderString (M/F/X)Low❌ No
emailString (Unique)High✅ Yes
statusEnum (5 types)Medium⚠️ Maybe
userIdObjectIdUnique✅ Yes

🛠️ How to Fix It

  • Avoid indexing low-cardinality fields unless paired in compound indexes
  • Instead, use the low-cardinality field in the suffix of a compound index if needed

📌 Example:

				
					db.orders.createIndex({ userId: 1, status: 1 })
				
			

Here, status is low-cardinality, but useful when combined with userId.


✅ 5. Forgetting to Analyze Query Plans

🔍 The Mistake

Developers skip the explain() method and assume the query is using the right index. MongoDB’s query planner sometimes picks suboptimal indexes, especially when many indexes exist.

⚠️ Why It’s a Problem

  • You may think your query is optimized, but it’s not
  • Wrong index = longer execution time
  • Even with correct indexes, queries may scan too many documents

🛠️ How to Fix It

  • Use .explain(“executionStats”) to evaluate how a query performs and which index it uses.

📌 Example:

				
					db.orders.find({ userId: 123, status: "shipped" }).explain("executionStats")
				
			

Sample output:

				
					"executionStats": {
  "nReturned": 10,
  "totalKeysExamined": 1000,
  "totalDocsExamined": 1000,
  ...
}
				
			

If totalDocsExaminednReturned, your index is inefficient.


⚡ Pro Tip

Use hint() to test index performance manually:

				
					db.orders.find({ userId: 123 }).hint({ userId: 1 })
				
			

This is useful for debugging or when tuning multiple index options.


🔧 Bonus: How to Audit Indexes Regularly

Here’s a simple routine you should adopt monthly (or during performance reviews):

  • List all indexes:
				
					db.collection.getIndexes()
				
			
  • Check index usage stats:
				
					db.collection.aggregate([{ $indexStats: {} }])
				
			
  • Check query plans for critical endpoints:
				
					db.collection.find({ ... }).explain("executionStats")
				
			
  • Drop unused indexes:
				
					db.collection.dropIndex("indexName")
				
			
  • Monitor query performance in MongoDB Atlas or Ops Manager

🔚 Final Thoughts

Indexing is arguably the most critical factor in MongoDB performance. Avoiding these common mistakes will not only improve query speed and efficiency but also reduce infrastructure costs, minimize CPU usage, and improve user experiences.

Remember:

  • Indexes are not magic — they need to be designed with your queries in mind.
  • Keep monitoring and iterating — workloads change over time.

Did you find this article helpful? Your feedback is invaluable to us! Feel free to share this post with those who may benefit, and let us know your thoughts in the comments section below.


📕 Related Posts