Request Unit Cost Analysis
Complete the full lesson to earn 25 points — 50 with Pro
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks, the wait, and see fewer ads — read each lesson on a single page with Pro
Module: Optimize Azure Cosmos DB Solution
Lesson: Request Unit (RU) Cost Analysis
Introduction: Why Request Units Matter
In the world of Azure Cosmos DB, the concept of the Request Unit (RU) is the fundamental currency of performance. Unlike traditional relational databases that rely on CPU, memory, and IOPS as separate metrics, Cosmos DB abstracts these resources into a single, unified metric: the Request Unit per second (RU/s). Understanding how to measure, analyze, and optimize the RU cost of your queries is not just a technical exercise; it is a financial and operational necessity. When your application scales, inefficient queries act as a hidden tax on your budget and a bottleneck for your end-user experience.
If you ignore RU consumption, you risk encountering "429 Too Many Requests" errors, which indicate that your application has exceeded its provisioned throughput. This leads to latency spikes, failed requests, and increased costs as you are forced to scale up your provisioned throughput to compensate for poorly written queries. By mastering RU cost analysis, you transition from simply "making it work" to building highly efficient, cost-effective, and predictable data architectures. This lesson will guide you through the mechanics of RU consumption, how to analyze query costs, and the strategies required to keep those costs at a minimum.
Understanding the Mechanics of Request Units
At its core, a Request Unit is a throughput measurement that encompasses the resources required to perform database operations. Whether you are performing a simple point read (fetching a document by ID and partition key) or a complex cross-partition query involving joins and aggregations, Cosmos DB calculates the cost based on the consumption of CPU, memory, and disk I/O.
When you execute a query, the Cosmos DB engine performs several internal steps:
- Query Parsing: The engine translates your SQL-like query into an internal representation.
- Index Traversal: The engine consults the index to find the documents that match your filter criteria.
- Document Retrieval: The engine fetches the actual documents from the storage layer.
- Projection and Transformation: The engine applies filters, sorts, and projections to format the result set as requested.
Each of these steps consumes a portion of the RU budget. A point read is generally very cheap—often around 1 RU—because it uses the partition key to go directly to the specific physical partition where the data resides. Conversely, a cross-partition query that performs a full table scan can cost hundreds or thousands of RUs because it must touch every single physical partition in your container.
Callout: The Economy of Point Reads vs. Queries Think of a point read as walking into a library and knowing exactly which shelf and book ID you need. You walk straight to the shelf, grab the book, and leave. This is highly efficient. A cross-partition query is like walking into the library and asking the librarian to check every single book on every shelf in the building to see if it matches your criteria. Even if you only find one book, the effort spent searching the entire library is massive. Always prefer point reads whenever your application design allows for it.
Analyzing Query Costs: The Tools of the Trade
To optimize, you must first measure. Cosmos DB provides several ways to inspect the RU cost of your operations. Every response from the Cosmos DB SDK includes a RequestCharge property. This is the gold standard for monitoring your application's real-time performance.
Using the Azure Portal Query Explorer
The Query Explorer in the Azure portal is the most accessible place to start. When you run a query, the "Query Stats" tab provides a breakdown of the RU cost. You will see the total RU charge for the execution, as well as metrics like "Retrieved document count" and "Retrieved document size."
- Open your Cosmos DB account in the Azure portal.
- Navigate to the "Data Explorer" tab.
- Select your database and container.
- Click "New SQL Query."
- Write your query and click "Execute Query."
- Look at the "Query Stats" tab at the bottom of the results pane.
Using the .NET SDK
When writing code, you should capture the request charge programmatically. This allows you to log high-cost queries to your application's telemetry (like Application Insights) for later analysis.
QueryDefinition queryDefinition = new QueryDefinition("SELECT * FROM c WHERE c.status = 'active'");
using FeedIterator<MyObject> resultSet = container.GetItemQueryIterator<MyObject>(queryDefinition);
while (resultSet.HasMoreResults)
{
FeedResponse<MyObject> response = await resultSet.ReadNextAsync();
double requestCharge = response.RequestCharge;
Console.WriteLine($"This batch cost {requestCharge} RUs.");
}
Tip: Always log your
RequestChargein your production environment. If a user reports a slow experience, checking the logs for that specific request ID will tell you exactly how many RUs that operation consumed, helping you isolate the culprit.
Factors Influencing RU Consumption
To optimize, you need to understand the "cost drivers" of your queries. Several factors contribute to the total RU cost of any given operation.
1. Indexing Policy
The indexing policy is the most significant factor in query cost. By default, Cosmos DB indexes every path in your JSON documents. While this makes queries fast, it increases the cost of write operations. If you have a massive index with many paths that you never actually query against, you are wasting RUs on index updates. Conversely, if you exclude a field from the index that you frequently use in a WHERE clause, your query will perform a full scan, which is extremely expensive.
2. Data Volume and Document Size
The size of the documents being returned or scanned directly impacts the RU cost. If you select all fields (SELECT *), you are pulling more data into memory than if you only select the specific fields you need (SELECT c.id, c.name). Large documents increase the I/O cost, as the engine must serialize and deserialize more bytes.
3. Cross-Partition vs. Single-Partition Queries
This is the "golden rule" of Cosmos DB optimization. A query that includes the partition key in the WHERE clause is a single-partition query. It is routed directly to the relevant partition. If you omit the partition key, the query becomes a cross-partition query. The engine must broadcast the query to every physical partition in your container, aggregate the results, and return them. The cost scales linearly with the number of physical partitions.
4. Filter Complexity
Complex filters involving multiple joins, subqueries, or expensive functions (like ST_DISTANCE or complex string manipulations) consume more CPU cycles. The more logic the engine must evaluate for every document, the higher the RU cost.
Step-by-Step: Optimizing a High-Cost Query
Let’s walk through a common scenario where a query is consuming too many RUs and how to fix it.
Scenario: You have an order history container. You are running this query to find orders for a specific user:
SELECT * FROM c WHERE c.status = 'shipped'
Step 1: Identify the problem.
This query does not include the userId (which is the partition key). It is a cross-partition scan. It is checking every order for every user in your database to see if the status is 'shipped'.
Step 2: Add the partition key.
Include the userId in the filter.
SELECT * FROM c WHERE c.userId = 'user123' AND c.status = 'shipped'
This immediately turns the query into a single-partition query, drastically reducing the RU cost.
Step 3: Refine the projection.
Instead of SELECT *, request only the necessary fields.
SELECT c.orderId, c.orderDate FROM c WHERE c.userId = 'user123' AND c.status = 'shipped'
This reduces the amount of data transferred and processed.
Step 4: Verify the index.
Ensure that the userId and status fields are included in the indexing policy. If you have a composite index on (userId, status), the engine can find the exact documents without needing to load them into memory first, which is even cheaper.
Comparison Table: Query Performance Characteristics
| Feature | Low RU Cost Pattern | High RU Cost Pattern |
|---|---|---|
| Partition Key | Included in WHERE clause |
Omitted (Cross-partition) |
| Projection | SELECT c.id, c.name |
SELECT * |
| Filter Logic | Simple equality checks | Regex, CONTAINS, OR operators |
| Indexing | Indexed fields | Unindexed fields (Table scan) |
| Ordering | Use index (Order by partition key) | Heavy sorting across partitions |
Advanced Optimization Techniques
Leveraging Composite Indexes
When your queries involve multiple filters or a filter combined with a sort, composite indexes are your best friend. A composite index allows the query engine to satisfy the filter and the order requirements using a single index lookup.
For example, if you frequently run:
SELECT * FROM c WHERE c.userId = 'user123' ORDER BY c.orderDate DESC
Without a composite index, the engine might have to retrieve all documents for the user and then sort them in memory. With a composite index on (userId, orderDate), the results are already sorted by date within the index for that specific user.
Avoiding "Expensive" Operators
Certain operators are inherently more expensive than others:
OR: UsingORacross different properties can prevent the query engine from effectively using the index.LIKE/CONTAINS: These require full scans of the indexed string values. If you need to search for text, consider using Azure Cognitive Search instead of forcing Cosmos DB to perform heavy string matching.- Functions in the
WHEREclause: Expressions likeWHERE UPPER(c.name) = 'JOHN'prevent the index from being used because the engine must apply theUPPERfunction to every record. Instead, store the name in the desired format (e.g., all uppercase) and query against that.
Warning: Avoid putting functions in your
WHEREclause. If you queryWHERE LOWER(c.email) = '[email protected]', the database cannot use the index on
Common Pitfalls and How to Avoid Them
1. The "Select Star" Trap
Many developers use SELECT * by default. This is the easiest way to inflate your RU costs. It forces the engine to return the entire document, including all nested objects and arrays. Only return what the UI or the next service in your pipeline actually needs.
2. The "Cross-Partition" Oversight
As your database grows, you will add more physical partitions. A query that seems "cheap" today because your database is small will become "expensive" tomorrow as the number of partitions increases. Always design your queries to include the partition key from day one, even if the current data set is small.
3. Ignoring Indexing Policy Updates
Developers often forget that the indexing policy is configurable. If you add a new query to your application that filters by a new field, you must ensure that field is included in your index. If it isn't, your new query will perform a full table scan and likely crash your throughput.
4. Excessive Use of OFFSET and LIMIT
Using OFFSET and LIMIT for pagination is a common pattern, but it is expensive. To get to page 100, the engine must skip the first 99 pages of results. This still consumes RUs for the items you are skipping. Use "continuation tokens" instead, which are the native way Cosmos DB handles pagination efficiently.
Callout: Continuation Tokens vs. Offset/Limit Continuation tokens work like a bookmark. When you request a page of results, the SDK returns a token that tells the database exactly where the last request left off. The next request starts exactly where the previous one finished. Offset and Limit, by contrast, require the database to count and ignore items from the start of the collection every time, which is wasteful and slow.
Best Practices for Long-Term Maintenance
- Monitor RU Trends: Use Azure Monitor to alert on high RU consumption. If you see a sudden spike, investigate the query logs immediately.
- Test Queries in Staging: Never push a new query to production without checking its RU cost in a staging environment that mimics your production data volume.
- Review Indexing Policy Regularly: As your query patterns change, your indexing policy should evolve. Remove unused indexes to save on write costs and add necessary indexes to support new query patterns.
- Use SDK Features: The latest versions of the Cosmos DB SDKs have built-in features for query optimization and diagnostics. Keep your SDKs updated to benefit from the latest performance improvements.
- Data Modeling: If your queries are consistently expensive, it might not be the query's fault; it might be your data model. If you are joining data across containers frequently, consider denormalizing your data into a single container to facilitate point reads.
Implementing a Query Cost Audit Process
To maintain a healthy Cosmos DB environment, you should implement a recurring audit process. This ensures that as your application evolves, you aren't accumulating "RU debt."
Step 1: Telemetry Collection
Ensure that all query executions are logged with their RequestCharge. Include the query text (or a hash of it) and the partition key used.
Step 2: Threshold Alerting Set alerts in Azure Monitor for "Request Charge" per query. If a query consistently exceeds a certain threshold (e.g., 50 RUs), trigger an automated notification to your development team.
Step 3: Periodic Review
Once a month, run a report to identify the "top 10 most expensive queries" by total RU consumption. Total RU consumption is calculated as: (Average RU per execution) * (Number of executions). A query that costs 10 RUs but runs 1,000,000 times a day is far more important to optimize than a query that costs 100 RUs but runs once a day.
Step 4: Refactoring Based on the report, prioritize the queries with the highest total impact. Apply the optimization techniques discussed earlier—adding composite indexes, including partition keys, or denormalizing the data model.
Key Takeaways
- RU is the Currency: Understand that every interaction with Cosmos DB has a cost. Managing this cost is as important as managing code quality.
- Prioritize Point Reads: Always strive to design your data model such that queries can target a specific partition key. This is the single most effective way to keep RU costs low.
- Measure Everything: Use the SDK's
RequestChargeproperty to track the cost of every query in production. If you aren't measuring it, you can't optimize it. - Projection is Key: Never use
SELECT *in production code. Select only the specific fields required to minimize data transfer and memory usage. - Indexing is a Tool, Not a Default: While default indexing is convenient, a custom indexing policy that aligns with your specific query patterns can save significant costs on both reads and writes.
- The Total Impact Metric: Focus your optimization efforts on queries that have high total consumption, not just those that have a high individual cost.
- Avoid Expensive Operators: Be wary of
OR,LIKE, and functions in theWHEREclause, as these often force the query engine to ignore your indexes and perform expensive full-collection scans.
By consistently applying these principles, you will ensure that your Azure Cosmos DB solution remains performant, scalable, and cost-effective, regardless of how much your data volume grows over time. Optimization is not a one-time task; it is an ongoing practice of monitoring, analyzing, and refining your data access patterns.
Reach the last section to complete this lesson and earn points — you're on section 1 of 10.
- Introduction to Cosmos DB Data Modeling
- Introduction to Cosmos DB Data Modeling Quiz5q
- Multiple Entity Types in Same Container
- Multiple Entity Types in Same Container Quiz5q
- Storing Related Entities in Same Document
- Storing Related Entities in Same Document Quiz5q
- Denormalizing Data Across Documents
- Denormalizing Data Across Documents Quiz5q
- Referencing Between Documents
- Referencing Between Documents Quiz5q
- Partition Keys and Document IDs
- Partition Keys and Document IDs Quiz5q
- Time to Live (TTL) Configuration
- Time to Live (TTL) Configuration Quiz5q
- Document Versioning Strategies
- Document Versioning Strategies Quiz5q
- Schema Versioning Patterns
- Schema Versioning Patterns Quiz5q
- Choosing Partition Strategies
- Choosing Partition Strategies Quiz5q
- Partition Key Selection Best Practices
- Partition Key Selection Best Practices Quiz5q
- Transactions and Partition Keys
- Transactions and Partition Keys Quiz5q
- Cross-Partition Query Costs
- Cross-Partition Query Costs Quiz5q
- Data Distribution Analysis
- Data Distribution Analysis Quiz5q
- Throughput Distribution Planning
- Throughput Distribution Planning Quiz5q
- Synthetic Partition Keys
- Synthetic Partition Keys Quiz5q
- Hierarchical Partition Keys
- Hierarchical Partition Keys Quiz5q
- Throughput and Storage Requirements
- Throughput and Storage Requirements Quiz5q
- Serverless vs Provisioned Throughput
- Serverless vs Provisioned Throughput Quiz5q
- Database-Level Provisioned Throughput
- Database-Level Provisioned Throughput Quiz5q
- Granular Scale Units
- Granular Scale Units Quiz5q
- Global Distribution Costs
- Global Distribution Costs Quiz5q
- Configuring Throughput in Portal
- Configuring Throughput in Portal Quiz5q
- Gateway vs Direct Connectivity Mode
- Gateway vs Direct Connectivity Mode Quiz5q
- Creating Database Connections
- Creating Database Connections Quiz5q
- Azure Cosmos DB Emulator
- Azure Cosmos DB Emulator Quiz5q
- Connection Error Handling
- Connection Error Handling Quiz5q
- Singleton Pattern for Clients
- Singleton Pattern for Clients Quiz5q
- Global Distribution Regions
- Global Distribution Regions Quiz5q
- Threading and Parallelism
- Threading and Parallelism Quiz5q
- Arrays and Nested Objects Queries
- Arrays and Nested Objects Queries Quiz5q
- Correlated Subqueries
- Correlated Subqueries Quiz5q
- Array and Type-Checking Functions
- Array and Type-Checking Functions Quiz5q
- Mathematical and String Functions
- Mathematical and String Functions Quiz5q
- Date Functions in Queries
- Date Functions in Queries Quiz5q
- Point Operations vs Query Operations
- Point Operations vs Query Operations Quiz5q
- CRUD Point Operations
- CRUD Point Operations Quiz5q
- Patch Operations for Updates
- Patch Operations for Updates Quiz5q
- Transactional Batch Operations
- Transactional Batch Operations Quiz5q
- Bulk Operations with SDK
- Bulk Operations with SDK Quiz5q
- Optimistic Concurrency with ETags
- Optimistic Concurrency with ETags Quiz5q
- Query Pagination and Continuation
- Query Pagination and Continuation Quiz5q
- Cosmos DB Mirroring for Fabric
- Cosmos DB Mirroring for Fabric Quiz5q
- Mirroring vs Spark Connector
- Mirroring vs Spark Connector Quiz5q
- Enabling Analytical Store
- Enabling Analytical Store Quiz5q
- Synapse Spark and SQL Queries
- Synapse Spark and SQL Queries Quiz5q
- Change Data Capture in Analytical Store
- Change Data Capture in Analytical Store Quiz5q
- Azure Functions and Event Hubs Integration
- Azure Functions and Event Hubs Integration Quiz5q
- Denormalization with Change Feed
- Denormalization with Change Feed Quiz5q
- Referential Integrity with Change Feed
- Referential Integrity with Change Feed Quiz5q
- Azure AI Search Integration
- Azure AI Search Integration Quiz5q
- Azure Functions Change Feed Trigger
- Azure Functions Change Feed Trigger Quiz5q
- Consuming Change Feed with SDK
- Consuming Change Feed with SDK Quiz5q
- Change Feed Estimator
- Change Feed Estimator Quiz5q
- Denormalization via Change Feed
- Denormalization via Change Feed Quiz5q
- Aggregation Persistence with Change Feed
- Aggregation Persistence with Change Feed Quiz5q
- Read-Heavy vs Write-Heavy Indexing
- Read-Heavy vs Write-Heavy Indexing Quiz5q
- Index Type Selection
- Index Type Selection Quiz5q
- Custom Indexing Policies
- Custom Indexing Policies Quiz5q
- Composite Index Implementation
- Composite Index Implementation Quiz5q
- Index Performance Optimization
- Index Performance Optimization Quiz5q
- Response Status Codes and Metrics
- Response Status Codes and Metrics Quiz5q
- Normalized RU Consumption Monitoring
- Normalized RU Consumption Monitoring Quiz5q
- Server-Side Latency Metrics
- Server-Side Latency Metrics Quiz5q
- Data Replication Monitoring
- Data Replication Monitoring Quiz5q
- Azure Monitor Alerts Configuration
- Azure Monitor Alerts Configuration Quiz5q
- Resource Logs Implementation
- Resource Logs Implementation Quiz5q
- Partition Throughput Monitoring
- Partition Throughput Monitoring Quiz5q
- Encryption Key Management
- Encryption Key Management Quiz5q
- Network-Level Access Control
- Network-Level Access Control Quiz5q
- Data Encryption Configuration
- Data Encryption Configuration Quiz5q
- Azure RBAC for Control Plane
- Azure RBAC for Control Plane Quiz5q
- Microsoft Entra ID for Data Plane
- Microsoft Entra ID for Data Plane Quiz5q
- CORS Settings Configuration
- CORS Settings Configuration Quiz5q
- Customer-Managed Keys
- Customer-Managed Keys Quiz5q
- Always Encrypted Implementation
- Always Encrypted Implementation Quiz5q
- Data Movement Strategy Selection
- Data Movement Strategy Selection Quiz5q
- SDK Bulk Operations for Data Movement
- SDK Bulk Operations for Data Movement Quiz5q
- Azure Data Factory Pipelines
- Azure Data Factory Pipelines Quiz5q
- Kafka Connector Integration
- Kafka Connector Integration Quiz5q
- Azure Stream Analytics Integration
- Azure Stream Analytics Integration Quiz5q
- Cosmos DB Spark Connector
- Cosmos DB Spark Connector Quiz5q
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles the points you earn on every lesson and quiz so you progress twice as fast, unlocks half of every practice exam — plus full case studies — with the Learn & Exam study modes, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× points per lesson & quiz
- ✓ 50% of every exam unlocked
- ✓ Learn & Exam modes
- ✓ Distraction-free lessons