Estimating the RU throughput requirements for Azure Cosmos DB and predicting cost
Tags: cosmosdb, cloud, programming, database
Published: 2023-05-30 15:42:26

Azure Cosmos DB is a globally distributed, multi-model database service designed to scale seamlessly to handle variable workloads.

One key aspect of Azure Cosmos DB's performance and scalability is its usage of Request Units (RUs). In Cosmos DB, RU throughput is important because it determines how many operations a database can perform per second. This means that by varying it, you can scale the performance of a database up or down, ensuring that your application can handle the expected workload and maintain the desired level of performance. Of course, this will also influence the cost you are billed for your database.

## Understanding Request Units (RUs)

Request Units (RUs) are a measure of the resources needed to perform a particular operation in Cosmos DB. Each database operation in Cosmos DB, such as reading, writing, or querying data, requires a specific number of RUs.

RUs are a fundamental part of the Cosmos DB pricing model. They determine the amount of throughput capacity that is required to perform a given set of operations on a database. The more RUs a database requires, the higher the cost of the database.

RUs are used to abstract the complexity of underlying hardware and software from the user. Instead of worrying about hardware and software configurations, users can simply specify the required RUs for their workloads, and Cosmos DB will handle the rest.

To estimate the required RU throughput for Azure Cosmos DB, it's important to consider the data operations that will be performed, the size of the data being accessed, and the performance characteristics of the database. The number of RUs required for a given data operation depends on the complexity of the query, the amount of data being accessed, and the consistency level of the database. In addition, the size of the data being stored, and the access patterns can affect the required RU throughput. For example, larger datasets may require more RUs to perform operations efficiently, and high-throughput workloads may require more RUs to ensure that the database can keep up with demand. By carefully considering these factors, users can estimate the required RU throughput for their specific workloads and ensure that their Cosmos DB database is provisioned with the appropriate amount of resources to handle their needs.

We will now explore some common Azure Cosmos DB operations and their associated RU costs to give you a better understanding of how RUs affect your database performance and cost.

### Reading a single document

Reading a single document by its ID and partition key is advertised as the solution that consumes the lowest number of RUs, making it the most efficient read operation in terms of RU usage. However, the size of the document drives the RU consumption and, for large documents, it will become more onerous that a query operation.

For example, reading a 1KB document will consume 1 RU, while reading a 100KB document will consume 10 RUs. Indexing has understandably no impact on RUs consumption of these operations.

### Creating a Document

Creating a new document in Azure Cosmos DB typically consumes a larger number of RUs than reading it, making it not particularly cost effective for write heavy scenarios. The RU cost for this operation depends on the size of the document and the amount of indexed fields.

For example, without any indexed field, writing a 1 KB document, will consume 5.5 RUs, while a 100KB document will consume 55 RUs. As you can see, as the document grows the cost scale the same as with reads.
Indexing has also an important impact, as inserting a 1KB document, with all fields indexed, which is the default behaviour, would consume about 16 RUs.

### Updating a Document

Updating a document consumes about double the RUs compared to creating a new document, however the RU consumption is potentially less affected by indexes as not necessarily all indexed fields are updated.

For example, without any indexed field, updating a field in a 1 KB document, will consume about 10 RUs, while in a 100KB document will consume 100 RUs.

### Sample RU consumptions

This table show measured RU charges for different operations on a sample 1Kb and 100Kb documents. Of course, there would be variation based on the actual shape of your documents.

|      | Insert | Point Read | Upsert | Delete |
| ---- | ------ | ---------- | ------ | ------ |
| 1KB Document<br>No Index | 5.5  | 1      | 10.3       | 5.5    |
1KB Document<br>All fields indexed (default) | 16.2 | 1      | 10.7       | 16.2   |
| 100KB Document<br>No Index | 48.8 | 10     | 96.7       | 48.8   |
| 100KB Document<br>All fields indexed (default) | 59.4 | 10     | 97.1       | 59.4   |

## Queries RUs consumption

When looking into the RUs consumption of queries, there are many different variables at play, which makes it more difficult to predict the performance and cost of performing the queries required to support your application behaviour.

### Indexes

In Azure Cosmos DB, indexes play a vital role in optimizing the performance of read and query operations. While indexing can increase the RU consumption of write operations, such as inserts and updates, the benefits of using indexes often outweigh the associated costs.

One of the main advantages of using indexes in Azure Cosmos DB is the substantial improvement in query performance. Indexes enable the database engine to quickly locate and retrieve documents based on specific attribute values. Without indexes, Cosmos DB would need to perform a full scan of the data, which is much slower and consumes more RUs. By using indexes, you can efficiently run complex queries with multiple filters, sorts, and joins, resulting in a significantly reduced query execution time and lower RU consumption.

It’s important to note that the number of total documents doesn't affect RUs consumption when running a query on an index in Cosmos DB because the query is executed on the index. However, the number of documents returned by the query does affect the RUs consumption, as it determines the amount of data that needs to be read and returned.

Cosmos DB offers automatic index management, which means that the database engine automatically maintains indexes for all properties in your JSON documents by default. This eliminates the need for manual index creation and maintenance, simplifying your database administration tasks. Automatic index management also ensures that new properties added to documents are indexed automatically, making your data model more flexible and adaptable to changes in your application. However, as we had seen previously, indexes come at a cost, so if you don’t need to perform queries on all fields, you should optimize your indexing policy to balance RU consumption and query performance.

Although indexing might increase the RU consumption of write operations, the benefits of faster query execution, automatic index management, and flexible indexing policies often outweigh the associated costs. By carefully perfecting your indexing strategy, you can strike the right balance between performance and cost efficiency in your Azure Cosmos DB deployment.

### Choosing the partition key

The choice of partition key in Azure Cosmos DB plays a crucial role in the overall performance and scalability of your database. A well-chosen partition key not only helps distribute your data evenly across multiple partitions but also affects the RU consumption of various operations.

#### Cross-partition queries

One of the main factors influencing RU consumption is the type of queries your application needs to perform. Queries that can be resolved within a single partition typically consume fewer RUs compared to queries that require scanning multiple partitions (cross-partition queries). By selecting a partition key that aligns well with your most common query patterns, you can minimize the number of cross-partition queries and reduce RU consumption.

#### Hot partitions

An inappropriate partition key choice may lead to a scenario where a single partition receives a disproportionately high amount of requests compared to others. Hot partitions can cause increased RU consumption and may result either in throttling, affecting your application's performance, or requiring you to increase the provisioned RUs of the whole database.
For this reason, to keep the RU consumption in check, it is critical to choose a partition key that evenly distributes the data and request load across all partitions.

#### Strategies for selecting an optimal Partition Key

While this is a big topic on its own, there are many resources available as it is not a problem specific to Azure Cosmos DB but a common requirement for most of the non-relational databases.
The best way to approach the problem is to first understand your application's most common query patterns and then choose a partition key that allows for efficient single-partition queries. Also consider the data distribution, select a partition key that ensures even distribution of data and request load across all partitions to prevent the problem of hot partitions.

Unfortunately, once a partition key is put in place, it is no longer possible to change it. However, this should not prevent you to continuously monitor your database's performance and RU consumption to identify potential issues with your partition key choice. Be prepared to migrate the data to a new container if the need to adjust your partition key strategy becomes necessary.

Sometimes, finding a partition key that works successfully in most scenarios is not possible and duplicating the data could unintuitively become the best option.

#### Leveraging data duplication for perfecting the partition key usage

There might be cases where a single partition key does not meet all query requirements efficiently. In such scenarios, duplicating data to another container with a different partition key can be a powerful strategy to optimize query performance and reduce RU consumption.

Duplicating data to another container with a different partition key can significantly improve the performance of queries that would otherwise require cross-partition operations. Cross-partition queries consume more RUs and have higher latency compared to queries that can be resolved within a single partition. The RU consumption of writing data to a new container could become negligible considering the saving on queries, depending on the volume of your operations.

#### Change Feed for data Synchronization

Azure Cosmos DB's Change Feed is a powerful feature that enables you to capture changes in your source container and replicate them to a target container with a different partition key. Change Feed ensures near-real-time data synchronization between the source and target containers, allowing you to maintain consistent data across multiple containers with different partition key configurations. This process is generally low effort and resilient, however it consumes RUs to read the data from the source container, on top of the obvious charges to write to the target container.

### Sample RU consumptions

There is a sample RUs consumption of a query using indexes on a container with documents of 1KB.

| Method     | Items Returned | RUs consumed with<br>1KB documents | RUs consumed with 100KB documents |
| ---------- | -------------- | ---------------------------------- | --------------------------------- |
| Point read | 1              | 1                                  | 10                                |
| Query      | 1              | 2.8                                | 4.5                               |
| Query      | 10             | 3.2                                | 19.9                              |

Based on the results of the sample test, the point read method appears to be the most efficient in terms of RUs consumption as it only consumes 1 RU for retrieving a single document. However, if the requirement is to retrieve multiple documents, then the query method becomes more efficient. It is important to note that the number of documents returned by the query has a significant impact on the RUs consumed. Therefore, when designing queries, it is important to consider the number of documents that will be returned and use indexing and query optimization techniques to minimize the RUs consumed.

In the last column we can see a test for larger documents that highlights an unexpected result due to a quirk of the Cosmos DB RU charges calculation. In fact, the point read are not actually the cheapest way to retrieve a single document as generally presented in the documentation, but for large documents retrieving items via query is actually cheaper.

## Translating RUs into cost

Now that we have a clear picture of the RUs consumption of different operations, we are left with the fundamental question on how RUs translate to cost in Azure Cosmos DB, so that we can better optimize our databases for cost efficiency. 

Azure Cosmos DB offers different pricing models, but the most relevant for this analysis are provisioned throughput and serverless.

Serverless is designed for workloads with variable or unpredictable throughput requirements, and you pay for the actual RUs consumed by your database operations instead of pre-allocating throughput capacity. It has, however, limitations on features availability and on how much your database can grow.

With provisioned throughput, you allocate a specific number of RUs per second to your database or container. This pre-allocated capacity determines the maximum throughput your database can handle at any given time. You are billed for the provisioned throughput, whether or not you fully utilize it.

Luckily, you can enable autoscaling on top of provisioned capacity, so that the provisioned throughput would instantly scale based on load, up to the specified maximum provisioned throughput and down to 10%. However, even if the scaling is near instantaneous, for each wall-clock hour you are charged for the maximum value reached of provisioned throughput in that hour, so supporting spiky workload can be expensive.

### Impact of partitioning and storage amount

One of the limitations of Azure Cosmos DB is that the provisioned throughput of all partitions scale together at the same time. While this doesn’t represent an issue for well distributed workloads, if you have many partitions and experience spikes of load in a small subset of those partitions, your required provisioned throughput and consequently cost will be significantly larger than would be expected given the amount of operations.

For example, if you have a large database of 40TB of data, you will probably have about a thousand physical partitions, due to the constraints on partitions size. If your data is not particularly well distributed and you have a spiky workload, it could easily be that you have a bunch of operations happening at the same time in one of the partitions at least once per hour.
Or, alternatively, you could have an infrequent unoptimized query requiring to scan multiple documents and hence consuming lots of RUs. In these cases, it would not be surprising to have a spike of consumption of a couple thousand RUs on  specific partitions. However, given all the partitions have to scale together, it would require a total provisioned capacity of a couple millions of RUs! If this happens every hour for just a second, you would be constantly paying for this high amount of RUs even if you are not actually performing that many operations on your database to justify this.

### Impact of data consistency and high availability on cost

In distributed databases that rely on replication, there is a fundamental trade-off between the read consistency, availability, latency, and throughput. The choice of data consistency and high availability settings can also a substantial impact on the cost of running the database.

First of all, adding more regions will multiply the cost as you are essentially paying for each region where your data is replicated to, independently from the amount of operations served by it. In fact, Cosmos DB provisioned throughput is reflected on all region, so even regions not serving any traffic will incur the same cost as the active region.

Azure Cosmos Db also offer the ability to setup a database in multi-region write, which offers better availability, while sacrificing the data consistency, but this causes the cost to double. So, if for example we have configured a database to have 3 regions with multi-region writes enabled, we would be paying 6 times compared to using a single region.

Regarding of the different consistency models, when using the Strong Consistency or the Bounded Staleness models to achieve better consistency, to the detriment of write latency, read operations will consume double the amount of RUs as they require a local minority quorum.

One final consideration is regarding the use of availability zones to improve the availability inside a single region. This introduces a 25% increase in cost for that region.

It is important to carefully evaluate the trade-offs between consistency, availability, and cost to ensure an optimal and cost-effective Cosmos DB solution.

## Estimating RUs requirements and predicting cost

Now that we understand the cost model of Azure Cosmos DB, we need to determine the amount of provisioned RUs that would be needed to support our applications, so that we can predict the running cost.

While there are many factors, as we discussed before, that influence how many RUs will be required to perform the operations happening every given second, if we managed to achieve a well-structured database, in particular with well-balanced partitions, we can obtain a pretty accurate figure focusing only on the main aspects: the amount of data, the size of the documents, the distribution of the different operations and the number of regions we are going to replicate the database to.

To quickly obtained an estimate based on this simplification, you can leverage the Azure Cosmos DB Capacity Planner which is provided for free by Microsoft to assist you in determining your RU needs based on your workload's characteristics.

You can access the Azure Cosmos DB Capacity Planner tool at the following URL: [Azure Cosmos DB Capacity Calculator](https://cosmos.azure.com/capacitycalculator)

The Capacity Planner tool requires you to input your workload details to provide a good estimate of RUs consumption and cost. It also provides the ability to define indicatively the difference in load between peak and quiet times, as well as to combine different workloads together. You will also need to specify the number of regions you are going to replicate your database to and if you intend to use multi-region writes which, has we had seen, has major cost implications.

The main omission in this tool is the lack of estimation of the cost of indexes, so your actual spend may vary based on how many indexes you have. As we have seen the major impact these have to the RUs consumption of create and update operations, so the variance can be significant for write heavy scenarios, which however are not ideal use cases for Cosmos DB.

The Capacity Planner tool provides a starting point for estimating your RU requirements. However, once you go live with your database, it's essential to monitor and adjust your provisioned throughput settings based on your actual usage patterns and performance metrics in a real-world scenario, and review your operations as needed.

## Monitoring RUs usage

Effectively monitoring and tuning Request Unit (RU) usage in Azure Cosmos DB is crucial for maintaining optimal performance and cost efficiency.

Azure Cosmos DB provides various tools and metrics to monitor your RU usage. The Azure Portal provides built-in metrics to inspect the RU usage of your Cosmos DB account. Key metrics include provisioned throughput, total requests, average RU consumption, and 429 (Too Many Requests) responses that show throttling due to exceeding provisioned throughput. You can also configure Azure Monitor to collect Cosmos DB metrics and create custom dashboards, alerts, and reports to track your RU usage.

Furthermore, when executing operations in Cosmos DB via the SDK in your application, you can retrieve metrics from the response, which include information on RU consumption, query execution time, and retrieved document count.

If you need more detailed information, you can enable diagnostic settings in your Cosmos DB account to collect logs and metrics, and send them to a storage account, event hub, or Log Analytics workspace for further analysis and reporting. Please note that there is a cost involved.

## Conclusion

In conclusion, this blog post has explored the significance of Request Units (RUs) in the context of Azure Cosmos DB, emphasizing their role in managing resources and controlling costs. We delved into the intricacies of query RU consumption, the translation of RUs into cost, estimation of RU requirements, and monitoring of RU usage.

The key takeaways from this post are:

- RUs are the primary measure of resource consumption in Cosmos DB and understanding them is crucial for optimizing performance and cost.
- The kind of operation and document size influence the RUs throughput requirements.
- Query RU consumption varies depending on factors like query complexity, indexing policies, and data size.
- Point reads are advertised as the most efficient way but in practice they consume more RUs than queries when dealing with large documents or where multiple documents need to be retrieved.
- RUs directly impact cost; hence, it's important to have a thorough understanding of the relationship between RUs and pricing.
- Estimating RU requirements and predicting costs is essential for budgeting and capacity planning.
- Regular monitoring of RU usage can help in identifying bottlenecks, optimizing performance, and avoiding unexpected costs.

We encourage you to make use of the provided resources to calculate and optimize your own RU throughput requirements for Cosmos DB. By taking advantage of this knowledge and the Azure Cosmos DB Capacity Planner tool, you can ensure that your database operations are both efficient and cost-effective. However, don't hesitate to explore further and tailor your Cosmos DB setup to suit your unique requirements. Happy optimizing!