Integrated Cache Implementation

Earn 25 points (50 with Pro) in two steps

  1. ① Read through the lesson — each section gets a ✓ as you scroll through it.
  2. ② When every section has a ✓, tap Complete lesson.

0 of 11 read · keep scrolling

✦ See fewer ads and earn double points — 50 a lesson instead of 25 — with Pro

Optimizing Azure Cosmos DB: Integrated Cache Implementation

Introduction: Why Query Performance Matters

In the world of distributed databases, performance is often defined by two metrics: latency and cost. When you build applications on top of Azure Cosmos DB, every request consumes Request Units (RUs). While Cosmos DB is designed for high-scale, low-latency operations, there are scenarios where your application repeatedly requests the same data, leading to unnecessary RU consumption and increased latency. This is where the Integrated Cache comes into play.

The Integrated Cache is a dedicated, in-memory cache that sits within your Cosmos DB gateway. Unlike an application-side cache (like Redis), the Integrated Cache is managed by the service itself. It allows you to cache both point reads and query results, significantly reducing the load on your physical storage partitions. Understanding how to implement and optimize this feature is a critical skill for any developer or architect looking to build cost-effective, high-performance applications on Azure. In this lesson, we will explore the mechanics of the Integrated Cache, how to configure it, and the best practices for ensuring it delivers the performance gains you expect.


Not read yet

Understanding the Integrated Cache Architecture

To effectively use the Integrated Cache, we must first understand where it lives in the request lifecycle. When a client application sends a request to Cosmos DB, it typically hits a gateway. If you are using the Integrated Cache, the request is intercepted by this memory layer before it ever reaches the physical storage nodes.

The Integrated Cache is specifically tied to the Dedicated Gateway. When you provision a dedicated gateway in your Cosmos DB account, you are essentially spinning up a set of compute resources that handle requests on behalf of your database. This gateway keeps a portion of its memory reserved for caching results. This architecture is powerful because it keeps the data closer to the request entry point, bypassing the overhead of indexing and partition routing for frequently accessed data.

Key Components of the Cache

  • Dedicated Gateway: The compute layer that acts as a front door to your database. It is required to enable the Integrated Cache.
  • Cache Policy: A set of rules that defines how long data should remain in the cache (Time-to-Live or TTL) and how the cache should be invalidated.
  • Request Consistency: The cache respects the consistency level of your request. If you request "Strong" consistency, the cache will ensure you receive the latest data, or it will bypass the cache if it cannot guarantee freshness.

Callout: Integrated Cache vs. Application-Side Caching Many developers are familiar with using Redis or in-memory caches within their application code. While application-side caching is excellent for reducing network hops, it adds complexity to your code regarding cache invalidation and serialization. The Integrated Cache is transparent to your application logic; it lives on the server side. This means you do not need to write custom logic to manage cache hits or misses in your application code, reducing the surface area for bugs.


Not read yet

Setting Up the Dedicated Gateway

Before you can implement the Integrated Cache, you must provision a Dedicated Gateway. This is a manual configuration step that involves selecting the right node size for your workload.

Step-by-Step Configuration

  1. Navigate to the Azure Portal: Go to your Cosmos DB account and look for the "Dedicated Gateway" section under the Settings menu.
  2. Provision the Gateway: Click "Create" and choose the appropriate node size (e.g., D4, D8, or D16). The choice of node size depends on your expected throughput and the memory requirements of your cached data.
  3. Update Connection String: Once the gateway is provisioned, you will receive a new connection string. You must update your application configuration to point to this dedicated gateway endpoint rather than the standard regional endpoint.
  4. Enable Integrated Cache in Client: In your SDK (e.g., the .NET SDK), you must explicitly enable the use of the Integrated Cache in your CosmosClientOptions.

Warning: Provisioning a Dedicated Gateway incurs a continuous hourly cost, regardless of whether you are actively querying the database. Ensure that your expected RU savings and latency improvements justify the cost of the dedicated compute nodes.


Not read yet

Configuring the Integrated Cache in Code

Once the infrastructure is in place, you need to instruct your application to utilize the cache. This is done through the CosmosClientOptions configuration. You must specify the ConnectionMode as Gateway because the Dedicated Gateway only supports gateway mode.

Implementing in .NET

// Define the client options
CosmosClientOptions options = new CosmosClientOptions()
{
    // The Dedicated Gateway requires Gateway mode
    ConnectionMode = ConnectionMode.Gateway,
    
    // Enable the integrated cache
    EnableIntegratedCache = true
};

// Initialize the client with the dedicated gateway endpoint
CosmosClient client = new CosmosClient(
    "your-dedicated-gateway-endpoint", 
    "your-primary-key", 
    options
);

In the example above, simply setting EnableIntegratedCache = true tells the SDK to start routing requests through the cache layer. However, the cache doesn't automatically store everything. You must also define the IntegratedCacheOptions for your specific queries.

Setting Cache TTL on Queries

By default, queries might not be cached unless you explicitly define the TTL or request it. You can set the IntegratedCacheOptions on the QueryRequestOptions object for each query execution.

QueryRequestOptions requestOptions = new QueryRequestOptions()
{
    // Set how long the results should stay in the cache
    IntegratedCacheOptions = new IntegratedCacheOptions()
    {
        CacheTTL = TimeSpan.FromMinutes(10)
    }
};

// Execute the query
FeedIterator<Product> iterator = container.GetItemQueryIterator<Product>(
    "SELECT * FROM c WHERE c.Category = 'Electronics'",
    requestOptions: requestOptions
);

Not read yet

Best Practices for Cache Optimization

Implementing the cache is only the first step. To get the most out of it, you need to follow industry-standard patterns.

1. Identify High-Frequency, Low-Volatility Data

The Integrated Cache is most effective for data that is read often but changed infrequently. If you have a product catalog that is updated once a day but queried thousands of times per second, this is a prime candidate for caching. Conversely, if your data changes every few seconds, the cache will constantly be invalidated, leading to "cache churn" and wasted resources.

2. Choose the Right TTL

The Time-to-Live (TTL) setting is a balance between performance and data freshness. A longer TTL reduces RU consumption significantly but increases the risk of users seeing stale data. A shorter TTL keeps data fresh but results in more frequent trips to the physical storage. Start with a conservative TTL (e.g., 60 seconds) and monitor the cache hit ratio before extending it.

3. Monitor Cache Hit Ratios

Use Azure Monitor to track the "Integrated Cache Hit Rate" metric. If your hit rate is below 50%, you may need to reconsider which queries you are caching or adjust your TTL settings. A low hit rate suggests that the cache is being cleared too often or that your application is querying a wide variety of unique data points that don't overlap.

Note: The Integrated Cache is shared across all containers within the same dedicated gateway instance. If you have multiple services sharing a gateway, be mindful of "noisy neighbor" scenarios where one high-volume service consumes all available cache memory, evicting data from other services.


Not read yet

Common Pitfalls and How to Avoid Them

Even with a well-configured cache, developers often run into issues that hinder performance. Here are the most frequent mistakes:

Over-Caching

The most common mistake is attempting to cache every single query. Caching requires memory. If your result sets are massive, you will quickly fill the cache, leading to frequent evictions. Only cache queries that return small, frequently accessed result sets. Avoid caching large, paginated result sets that change on every request.

Ignoring Consistency Requirements

As mentioned earlier, the cache respects consistency levels. If your application requires Strong consistency, the Integrated Cache will often bypass the cache to ensure the data is accurate. If you find that your cache isn't being used despite being enabled, check your consistency settings. You might be using a consistency level that is incompatible with the cache's current operating mode.

Failing to Size the Gateway Correctly

If you select a gateway node that is too small for your workload, the memory pressure will cause the cache to evict items prematurely. Always monitor the "Dedicated Gateway CPU" and "Memory Usage" metrics in the Azure portal. If you see high memory pressure, it is time to scale up your gateway nodes to a larger SKU.


Not read yet

Quick Reference: Comparison of Caching Strategies

Feature Integrated Cache Application-Side (Redis)
Location Server-side (Gateway) Client-side/External
Management Managed by Cosmos DB Managed by Developer
Consistency Integrated with DB Manual invalidation required
Complexity Low (Configuration-based) High (Code-based)
Best For Reducing RU costs, server-side offload Extreme low latency, complex data structures

Advanced Scenarios: Handling Cache Invalidation

One of the biggest challenges in distributed systems is cache invalidation—the process of ensuring that when data changes in the database, the cache is updated or cleared. The Integrated Cache handles this automatically for point reads (when you read by ID), but complex queries are more nuanced.

When you execute a query, the result is cached based on the query text and the parameters. If an underlying document is updated, the Integrated Cache is smart enough to invalidate the relevant result sets, but this only happens if the gateway is aware of the change. This is why it is vital to use the Dedicated Gateway for both reads and writes if you want the most seamless experience.

When to Bypass the Cache

Sometimes, you explicitly want to avoid the cache. Perhaps you are running an administrative task that requires the absolute latest data from the physical partition. In these cases, you can set the IntegratedCacheOptions to null or explicitly configure the request to ignore the cache.

QueryRequestOptions bypassOptions = new QueryRequestOptions()
{
    // Setting to null or omitting forces a read from the physical storage
    IntegratedCacheOptions = null 
};

This is useful for:

  • Audit logs: Where you need to ensure you are seeing every single transaction.
  • Administrative dashboards: Where data accuracy is more important than speed.
  • Troubleshooting: When you suspect that a user is seeing stale data and you need to verify the source of the truth.

Not read yet

Monitoring and Debugging Performance

To optimize your implementation, you must become proficient with the metrics provided by Azure. The "Integrated Cache Hit Rate" is your primary metric. However, you should also monitor "Integrated Cache RU Consumption."

If you see high RU consumption despite having a high cache hit rate, it usually means that your cache-miss queries are extremely expensive. Check the RU cost of your non-cached queries. You might find that a few "heavy" queries are driving your costs, even if the majority of your traffic is successfully served by the cache.

Tips for Debugging:

  1. Use Diagnostic Logs: Enable diagnostic logs for your Cosmos DB account. Look for the IntegratedCache category in the logs. This will provide detailed information about why a query was or was not served from the cache.
  2. Analyze Query Metrics: When you run a query, the SDK returns a QueryMetrics object. Check the IntegratedCacheHit property. If it is false, the query went to the storage layer.
  3. Check for "Partition Key" mismatches: Ensure your queries are using the partition key effectively. A cross-partition query is more likely to be expensive and less likely to be cached efficiently than a single-partition query.

Not read yet

Best Practices for Scaling

Scaling the Integrated Cache is not just about adding more nodes; it is about scaling your data access patterns. As your application grows, consider the following:

  • Implement Read-Heavy/Write-Heavy Separation: If possible, use the Dedicated Gateway for your read-heavy services and a separate, non-gateway endpoint for your write-heavy background processes. This prevents write-heavy workloads from interfering with the cache efficiency of your read-heavy services.
  • Optimize Query Text: The cache keys are based on the exact query string. If your application dynamically generates SQL strings (e.g., SELECT * FROM c WHERE c.id = '123' vs SELECT * FROM c WHERE c.id = '456'), the cache will treat these as unique entries. Use parameterized queries! Parameters ensure that the query template is identical, allowing the cache to serve results for different parameter values efficiently.

Example of Parameterized Query (Cache-Friendly)

// BAD: Dynamic strings cause cache misses
string query = "SELECT * FROM c WHERE c.Category = '" + categoryName + "'";

// GOOD: Parameterized queries allow the cache to reuse the template
QueryDefinition queryDef = new QueryDefinition("SELECT * FROM c WHERE c.Category = @cat")
    .WithParameter("@cat", categoryName);

By using parameters, the database engine and the Integrated Cache can treat the query as a single template, significantly increasing the probability of a cache hit. This is one of the most impactful optimizations you can make.


Not read yet

Future-Proofing Your Implementation

As Azure Cosmos DB evolves, the capabilities of the Integrated Cache are likely to expand. Keep an eye on updates regarding cache eviction policies and cache size management. Currently, the cache is managed automatically, but as your data volume grows, you may need to reconsider your architecture.

If you find that the Integrated Cache is consistently failing to meet your needs due to memory constraints or complex caching requirements, do not be afraid to pivot to a hybrid approach. Some developers use the Integrated Cache for high-frequency, simple queries and a side-car cache (like Redis) for complex, multi-join, or aggregation-heavy results. This hybrid strategy allows you to leverage the simplicity of the Integrated Cache for the "easy wins" while maintaining control over the more complex data requirements.


Key Takeaways

  1. The Integrated Cache is a server-side performance tool: It lives in the Dedicated Gateway and intercepts requests, reducing latency and RU consumption without requiring complex client-side code.
  2. Dedicated Gateway is mandatory: You cannot use the Integrated Cache without provisioning dedicated gateway nodes. Always account for this cost in your architectural planning.
  3. Parameterized queries are essential: Because cache keys are based on the query string, using parameters ensures that your queries are treated as reusable templates, which is critical for achieving a high cache hit rate.
  4. Monitor your hit rate: Use Azure Monitor to keep an eye on your cache hit ratio. If it is consistently low, investigate your query patterns and TTL settings.
  5. Balance TTL and freshness: Choose a TTL that reflects the volatility of your data. Don't be afraid to use shorter TTLs for data that changes frequently.
  6. Understand the consistency trade-offs: The cache respects consistency levels. Ensure your application's consistency requirements align with how the cache operates, or you may find yourself bypassing the cache unintentionally.
  7. Right-size your gateway: Monitor the CPU and memory of your dedicated gateway nodes. If you hit memory limits, you will experience cache evictions that degrade performance across the board.

By following these practices, you can effectively leverage the Integrated Cache to build highly performant, cost-efficient Cosmos DB solutions that scale with your application's needs. Remember that performance optimization is an iterative process—start with the basics, monitor the results, and refine your approach based on real-world data from your production environment.


Not read yet

Frequently Asked Questions (FAQ)

Q: Can I use the Integrated Cache with the standard Cosmos DB endpoint? A: No, the Integrated Cache requires the use of the Dedicated Gateway endpoint.

Q: Does the Integrated Cache work for all consistency levels? A: It works for all levels, but requests with "Strong" consistency may bypass the cache if the system cannot guarantee that the cached data is current.

Q: Is the Integrated Cache shared across different databases in the same account? A: Yes, the cache is provisioned at the gateway level and is shared across all containers and databases accessed through that gateway.

Q: How do I know if my query is hitting the cache? A: Check the QueryMetrics in your SDK response or review the diagnostic logs in Azure Monitor to see the IntegratedCacheHit status.

Q: What happens if I scale down my Dedicated Gateway? A: Scaling down your gateway will reduce the available memory for the cache, which will likely lead to increased cache evictions and a drop in your hit rate. Monitor your metrics closely during scaling operations.

Not read yet

Each section gets a ✓ as you scroll through it. Tap the button to jump to the next one.