MongoDB is the premier NoSQL document database for modern developers working on high-performance applications. With its JSON-like documents, MongoDB is notable for horizontal scaling and load balancing, which offers developers an excellent balance of customization and scalability.
But like any high-performance tool, MongoDB performs best in the hands of an expert who knows what they’re doing. Performance issues may indicate that the database is not working as hard as it could and that specific optimizations could lead to better performance.
In this post, we’ll focus on how to achieve performance at scale using MongoDB by looking at:
Please keep in mind that the best practices we are going to cover are not exhaustive (that would require a much longer post).
While anyone interested in document database platforms could learn something from this post, you’ll probably find this information particularly useful if you’re:
Starting your first project as a seasoned MongoDB developer.
Running MongoDB on Atlas, the fully managed, global cloud database service
Managing MongoDB yourself
If you only have a few minutes to spare, this quick performance FAQ might be useful:
Ad hoc queries, indexing, and real time aggregation provide powerful ways to access data. MongoDB is a distributed database by default, which allows for expansive horizontal scalability without any changes to application logic.
Pretty darn fast. Primary key or index queries should take just a few milliseconds. Queries without indexes depend on collection size and machine specs, etc.
It depends on what you are and aren’t doing already. Try adding indices. Don’t do joins (embedding is preferable). Upgrade your machine specs. And, if you haven’t, definitely try sharding for horizontal scaling.
MongoDB needs enough RAM to hold your working set in memory. Of course, the exact answer depends on your data size and your workloads. You can use MongoDB Atlas for auto-scaling.
Yes, it most certainly is. MongoDB is great for large datasets. MongoDB Atlas can handle federated queries across object storage (e.g., Amazon S3) and document storage.
Without further ado, let’s go over the top 5 best practices for getting peak performance out of your MongoDB databases.
Most developers would agree that the first step in optimizing performance is to understand expected and actual query patterns. Once you know your application’s query patterns like the back of your hand, you can design your data model and select appropriate indices accordingly.
With MongoDB, developers have access to several powerful tools that can help them greatly improve performance—but that doesn’t mean that query patterns and profiles can be ignored, either.
For example, one easy way to beef up performance is by simply analyzing your query patterns and determining where you can embed data rather than doing in-application or in-database joins.
Other ways to improve MongoDB performance after identifying your major query patterns include:
Storing the results of frequent sub-queries on documents to reduce read load
Making sure that you have indices on any fields you regularly query against
Looking at your logs to identify slow queries, then check your indices
MongoDB is noted for its flexible schema, but this doesn’t mean that you can ignore schema design best practices. You should always figure out your schema at the beginning of a project so that you won’t have to retool everything later on. This applies 100% to your data models.
While designing your data model, you must decide how to model relationships between data. Deciding when to embed a document or create a reference between separate documents in different collections instead, for example, is an application-specific consideration.
A major advantage of JSON documents is that they allow developers to model data however the application requires. Nesting arrays and subdocuments allow you to model complex relationships between data using simple text documents.
But using MongoDB, you can also model:
flat, tabular, and columnar structures
simple key-value pairs
nodes and edges of connected graph data structures, etc.
Data modeling is a vast and sprawling topic that you could spend months learning about. If you haven’t already, here are a few resources that might help:
MongoDB documentation includes a great section on data modeling, starting from planning out your document data model and going into detail on specifics such as embedding and referencing.
MongoDB University offers a free training course on data modeling. This is a great way for beginners to get started with schema design and document data models.
A natural extension of data modelling, embedding allows you to avoid application joins, which minimizes queries and updates.
Notably, data with a 1:1 relationship should be embedded within a single document. Data with a 1:many relationship in which "many" objects appear with or are viewed alongside their parent documents are also great candidates for embedding. Because these types of data are always accessed together, storing them together in the same document just makes sense.
Embedding generally provides better performance for read operations due to this kind of data locality. Embedded data models also allow developers to update related data in a single write operation because single document writes are transactional.
However, not all 1:1 and 1:many relationships are good candidates for embedding in a single document. That’s where referencing between documents in different collections comes in.
Referencing makes much more sense when modeling many:many relationships. However, whenever referencing, your application must issue follow-up queries to resolve any references. This, in turn, requires more round-trips to the server.
You should consider referencing when:
A document is frequently accessed but contains data that is rarely used. Embedding would only increase in-memory requirements, so referencing may make more sense.
A part of a document is frequently updated and keeps getting longer, while the remainder of the document is relatively static.
The document size exceeds MongoDB’s 16MB document limit. This could occur when modeling many:1 relationships, such as product reviews:product, for example.
As with most databases, MongoDB performs best when an application’s working set (e.g., indices and frequently accessed data) fits in memory without issue. While other factors play a part in performance, RAM size is obviously the most important consideration for instance sizing.
When an application’s working set fits in RAM, read activity from the disk should be low. But if your working set exceeds the RAM of the instance size or server, read activity will begin to shoot up. If you notice this happening, you may be able to solve the problem by moving over to a larger instance with more memory.
Or you could partition (shard) your database across multiple servers (more on this later).
Properly sizing your working set is crucial whether you’re running MongoDB Atlas or managing MongoDB yourself. If you’re using Atlas, remember to always review your Atlas sizing and tier selection documentation to properly calculate the size of your working set.
It’s worth pointing out that in MongoDB Atlas, scaling memory is automated and straightforward. You can opt into cluster tier auto-scaling, for example, which automatically adjusts compute capacity in response to real-time changes in application demands.
No discussion of increased performance or horizontal scaling is complete without mentioning replication, which increases data availability via horizontal scaling. Replication can lead to better performance and also offers redundancy, which provides more security.
In MongoDB, replication is accomplished via replica sets that allow developers to copy data from a primary server or node across multiple secondaries. This allows your application to run some queries on secondaries instead of the primary, avoiding contention and leading to improved load balancing.
Replica sets provide several advantages to MongoDB developers:
Redundancy and data availability: Replication can be very helpful in case of disastrous events like hardware failures or server crashes. Should a primary node fail, an election process will automatically elect a new primary node from the remaining secondary nodes.
Load sharing: Replica sets offer better scalability for your applications. As an example, developers can configure their applications to read from multiple servers to help with load balancing among replica sets.
Data locality: In terms of performance, replication also improves latency for read usage. If you have the same data spread out across multiple servers, that data can be accessed at the location closest to the end user.
Sharded clusters in MongoDB are another way to potentially improve performance. Like replication, sharding is a way to distribute large data sets across multiple servers. Using what’s called a shard key, developers can copy pieces of data (or “shards”) across multiple servers. These servers work together to utilize all of the data.
Sharding comes with several advantages, including horizontal scaling for reads/writes as well as increased storage capacity and higher availability.
Once again, this is a non-comprehensive list of the top performance best practices for MongoDB. As any experienced database developer will tell you, there are a thousand and one things you can do to improve performance—and they all depend on your exact application.
More importantly, always remember that appropriate data modeling, indexing, embedding, and referencing are basic considerations. Assuming you know the query patterns of your application well, you’ll find that you can get solid performance and a lot of extra mileage out of the distributed and replicated nature of MongoDB.
If all else fails...did we mention that MongoDB Atlas also has a built-in Performance Advisor? It can make your life a whole lot easier if you’re not sure where to start.