Cosmos DB: how to query a specific region?

Cosmos DB can be configured with a Geo-Redundancy feature enabled. In such situation, it is supposed to replicate data to multiple regions. We should also be able to read from all of those regions. In this article, you will learn how to query a specific region of an Azure Cosmos DB database.

In the Azure Portal, the geo-redundancy feature comes with a nice visualization in a form of a map:

The “Replicate data globally” pane in Azure Portal. It shows which regions are selected as Write Regions and Read Regions in a Cosmos DB instance.
The feature to “Replicate data globally” in Azure Portal’s UI for Cosmos DB

Looking at the above map, it appears that everything works. But I was asked for a short demo to prove that we can really query any of the regions with the expectation that we’ll receive the same results from all of them. Sounds easy, but was it really?

Surprisingly, not so easy because the following methods did not work:

  • Query specific region from the Azure Portal (from the Data Explorer pane).
    That didn’t work because there appears to be no UI element that would allow us to choose which region to query. Furthermore, after the service executes the query, there is no post-factum information about which region was queried.
  • Query specific region from Azure Storage Explorer.
    Similarly, no support in UI for such query. The UI displays the primary region as a hint, but it doesn’t display other regions nor allow querying them.

So, what method would allow us to demo that data is available in other regions?

  • Query specific region using Cosmos DB SDK. This method allowed me to query the specific region I wanted. You will find code sample is in the next section.
  • Query specific region via REST API. If we were able to issue the query via SDK, it must also be possible via REST API. I didn’t dig into that option because authorizing a REST request to Cosmos API is a challenge itself, and using SDK seems simpler.

Querying specific region from Cosmos DB SDK

So, the most practical method to demonstrate the feature that I found was with the use of Cosmos DB SDK.

Let me do a shortcut here and just provide the demo code with the key line highlighted.

// Note: project should reference Microsoft.Azure.Cosmos 3.23.0 or newer

using System;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos;

namespace CosmosDbQuerySpecificRegion
{
    internal class Program
    {
        private static async Task Main()
        {
            await TryQuerySpecificRegion(Regions.WestEurope); // will contact WestEurope
            await TryQuerySpecificRegion(Regions.NorthEurope); // will contact NorthEurope
            await TryQuerySpecificRegion(Regions.AustraliaCentral); // will contact WestEurope (the default, because we don't replicate to Australia)
        }

        private static async Task TryQuerySpecificRegion(string region)
        {
            var cosmosEndpointUrl = "https://CENSORED.documents.azure.com:443/";
            var cosmosPrimaryKey = "CENSORED==";
            var cosmosClient = new CosmosClient(cosmosEndpointUrl, cosmosPrimaryKey, new CosmosClientOptions
            {
                ApplicationRegion = region // here's where we specify the region!
            });

            var container = cosmosClient.GetContainer("MyDatabaseId", "MyContainerId");
            var response = await container.GetItemQueryIterator<MyDocument>("SELECT * FROM c").ReadNextAsync();
            var regions = response.Diagnostics.GetContactedRegions();

            Console.WriteLine($"Attempted to contact region '{region}'. Actually contacted: {string.Join(", ", regions)}");
            Console.WriteLine($"Your query returned {response.Count} records"); // all regions are expected to return the same data!
            Console.WriteLine("");
        }
    }

    internal record MyDocument(string Id, string UserId);
}
Code language: C# (cs)

The above program returns the following output when we run it against the database with 2 regions (i.e., WestEurope and NorthEurope):

The result of querying specific Cosmos DB regions for data. The result includes cases when region has the data and when it doesn't have it.
Output of a demo program

When we attempted to query a region, where I have not configured any database instance (i.e., Australia Central), we see that query doesn’t fail with an exception but is run against the primary region and succeeds anyway.

Thanks for stopping by!

Leave a Comment