Configure throughput and consistency in Python

In this exercise, you adjust autoscale throughput, compare read charges at strong and eventual consistency, and configure time to live (TTL). You test item-level expiration in the product catalog and a default lifetime in a separate container.

This exercise takes approximately 30 minutes to complete.

Before you start

To complete this exercise, you need an Azure subscription with permission to create resources and assign roles.

If your lab environment isn’t set up yet, follow Set up your lab environment to install Visual Studio Code, Git, the Azure CLI, and PowerShell 7.

You also need Python 3.12 or 3.13 installed.

Set up your Azure Cosmos DB resources

The core exercises reuse an account prepared with the core profile, not the two-item account from the first portal exercise. Before skipping setup, open Allfiles/Labs/Shared in PowerShell, sign in with az login, and set $resourceGroup, $location, and $accountName to your recorded values. Run ./verify.ps1 -ResourceGroup $resourceGroup -AccountName $accountName -LabProfile core and continue only when it succeeds. In Data Explorer, confirm 295 items in cosmicworks/product and 237 in cosmicworks/productMeta with SELECT VALUE COUNT(1) FROM c.

If you have no verified core account, follow the setup steps below. To add missing resources to an existing lab account, pass its explicit -AccountName to setup rather than using a different module’s name prefix. Reseeding restores canonical items but doesn’t remove extra items or reset container policies. Resolve mismatches before continuing; don’t reset a shared account automatically.

  1. Start Visual Studio Code.

  2. If you don’t have the lab code yet, clone the repository for DP-420: open the command palette with Ctrl+Shift+P, run Git: Clone, and enter the following URL. Choose a local folder when prompted. Otherwise, open the folder from your previous clone.

     https://github.com/microsoftlearning/dp-420-cosmos-db-dev
    
  3. Once the repository is cloned, open that local folder in Visual Studio Code.

  4. In the Explorer pane, browse to the Allfiles/Labs/Shared folder.

  5. Open the context menu for the folder and select Open in Integrated Terminal. If the terminal isn’t PowerShell, select the dropdown beside the + in the terminal toolbar and choose PowerShell.

  6. Sign in to the Azure CLI. A browser window opens so you can sign in to Azure.

     az login
    
  7. Set variables for the resource group (If a resource group was provided by your lab environment, use that name) and region you want to use. Change either value if you prefer a different resource group name or region.

     $resourceGroup = "ResourceGroup1"
     $location = "westus2"
    
  8. Run the setup script.

     ./setup.ps1 -ResourceGroup $resourceGroup -Location $location -NamePrefix dp420lab02 -LabProfile core
    

    Azure Cosmos DB account names have to be globally unique, so the script builds one for you by adding six random characters to the prefix, giving a name like dp420lab02a7f3k9.

  9. Wait for the script to finish. The whole script takes 5-10 minutes to run.

  10. Record the Account name and Account endpoint values the script prints. You need the endpoint later in this exercise, and it looks like https://<your-account-name>.documents.azure.com:443/.

The script creates the following resources:

Resource Configuration
Azure Cosmos DB account API for NoSQL, with key-based authentication disabled
cosmicworks database Holds the containers for the core lab profile
product container Partitioned on /categoryId, autoscale up to 1,000 RU/s, loaded with 295 CosmicWorks products
productMeta container Partitioned on /type, autoscale up to 1,000 RU/s, loaded with 237 metadata items
leases container Partitioned on /id, manual throughput of 400 RU/s
operations and bulkload containers Each partitioned on /categoryId, with its own autoscale maximum of 1,000 RU/s
Role assignment Cosmos DB Built-in Data Contributor, granted to your signed-in identity

Because key-based authentication is disabled, no key or connection string appears anywhere in this exercise. Every operation authenticates with the identity from your az login session, which is the recommended approach for new accounts.

📝 A new role assignment takes a few minutes to propagate. If a later step fails with a 403 error, wait a moment and try again.

Review the autoscale range

Autoscale scales between 10 percent of the maximum you set and that maximum. Confirm that range in the portal.

  1. In a web browser, open the Azure portal, sign in, and go to your Azure Cosmos DB account.

  2. In the resource menu, select Data Explorer.

  3. In the Data Explorer pane, expand the cosmicworks database, select the product container, and then select Scale and Settings.

  4. Review the Scale section. The Autoscale option is selected, and the maximum throughput is 1,000 RU/s.

    The container scales between 100 RU/s and 1,000 RU/s based on demand. Throughput is billed at the highest level reached in each hour, with a minimum of 100 RU/s even when idle.

  5. Change Maximum RU/s to 4000 and select Save. Wait for the update to finish and confirm that the displayed range is 400 RU/s to 4,000 RU/s.

    A higher autoscale maximum also raises the minimum throughput and baseline cost.

  6. Set Maximum RU/s back to 1000 and select Save. Wait for the update to finish and confirm that the displayed range returns to 100 RU/s to 1,000 RU/s.

  7. Open the context menu for product in the database tree and select New SQL Query. Confirm that the query tab belongs to product, then run the following query to confirm that the loaded count is 295:

     SELECT COUNT(1) AS itemCount
     FROM c
    

Set the account default consistency level

The account default applies to every read unless a client or request relaxes it. Set it to strong so you can observe the cost difference when you relax it.

  1. In the Settings menu, select Default consistency.

  2. Select Strong, and then select Save.

  3. Wait for the change to apply before continuing.

    📝 Strong consistency reads from more than one replica to guarantee the latest committed write.

Measure the request charge at each consistency level

Now connect from code and compare the request charge of the same read at strong and eventual consistency.

  1. In a terminal, create a project folder and set up a virtual environment:

     mkdir throughput-lab
     cd throughput-lab
     python -m venv .venv
    
  2. Activate the environment. On Windows:

     .venv\Scripts\activate
    

    On macOS or Linux:

     source .venv/bin/activate
    
  3. Install the required packages:

     pip install azure-cosmos azure-identity
    
  4. In the throughput-lab folder, create script.py with the following code. Replace <cosmos-endpoint> with the account endpoint the setup script printed:

     from azure.cosmos import CosmosClient
     from azure.identity import DefaultAzureCredential
    
     endpoint = "<cosmos-endpoint>"
    
     # Use a developer credential, such as az login, rather than an account key.
     # Without a consistency override, reads use the account default.
     client = CosmosClient(url=endpoint, credential=DefaultAzureCredential())
     container = client.get_database_client("cosmicworks").get_container_client("product")
    
     # Together, the item ID and /categoryId value identify one product for a point read.
     item_id = "0A7E57DA-C73F-467F-954F-17B7AFD6227E"
     partition_key = "4F34E180-384D-42FC-AC10-FEC30227577F"
    
     def print_charge(label):
         # Read the request charge from the response headers.
         def hook(headers, response):
             print(f"{label} request charge:\t{headers['x-ms-request-charge']} RUs")
         return hook
    
     container.read_item(
         item=item_id,
         partition_key=partition_key,
         response_hook=print_charge("STRONG"))
    

    The response hook reads x-ms-request-charge from the response headers.

  5. Run the script:

     python script.py
    
  6. Review the output. The charge reflects strong consistency:

     STRONG request charge:  2 RUs
    
  7. Create a second client configured for eventual consistency. Add the following code to the end of script.py:

     # Relax reads for this second client without changing the account's policy.
     # Read the same item so the comparison changes only consistency.
     eventual_client = CosmosClient(
         url=endpoint,
         credential=DefaultAzureCredential(),
         consistency_level="Eventual")
    
     eventual_container = (eventual_client
         .get_database_client("cosmicworks")
         .get_container_client("product"))
    
     eventual_container.read_item(
         item=item_id,
         partition_key=partition_key,
         response_hook=print_charge("EVENTUAL"))
    

    The consistency_level argument relaxes every read from this client below the account default.

  8. Run the script again:

     python script.py
    
  9. Compare the two charges:

     STRONG request charge:    2 RUs
     EVENTUAL request charge:  1 RUs
    

    For the same item, a strong-consistency read costs about twice an eventual-consistency read. Relax consistency only when the application can tolerate stale data.

  10. The consistency override used here can weaken reads but can’t exceed the account default. Set the account default to the strongest level your application needs, then relax reads where appropriate.

  11. When you finish testing, deactivate the Python environment:

     deactivate
    

Restore the account default consistency

Restore Session consistency before continuing with later exercises.

  1. Return to the Azure portal and open your Azure Cosmos DB account.

  2. In the Settings menu, select Default consistency.

  3. Select Session, and then select Save.

    Wait for the update to finish. Restart any running application so its client picks up the new default.

Configure time to live and observe expiry

Test item-level TTL on product and a container default on a disposable container.

  1. Return to the Azure portal and open the Data Explorer.

  2. Expand the cosmicworks database, select the product container, and then select Scale and Settings.

  3. In the Settings tab, find Time to Live and select On (no default).

    On (no default) sets the container TTL to -1. Only items with a positive ttl value expire.

  4. Select Save.

  5. Select Items, and then select New Item. Add an item with a ttl property set to 60 seconds, and then select Save:

     {
       "id": "temp-record-001",
       "categoryId": "4F34E180-384D-42FC-AC10-FEC30227577F",
       "name": "Temporary record",
       "ttl": 60
     }
    
  6. Select New SQL Query under the product container and run the following query:

     SELECT * FROM c WHERE c.id = "temp-record-001"
    

    Initially, the query returns the item you just added.

  7. Wait about 90 seconds, then run the query again.

    The expired temp-record-001 item no longer appears in query results. ML Road Pedal remains because it has no ttl value and the container has no default lifetime.

  8. In the product container’s Scale and Settings, change Time to Live back to Off and select Save. Wait for the update to finish.

    ⚠ Don’t set a positive default TTL on the shared product catalog. Expiration is measured from each item’s last modification, not from when TTL is enabled. Existing items older than the default TTL can expire immediately.

  9. Run the temporary-item query again after TTL is Off. If temp-record-001 is still present, delete only that test item:

    • Open Items and filter for WHERE c.id = "temp-record-001".
    • Select the item and verify that its id and categoryId match the test item. Then select Delete and confirm.
    • Run the query again and confirm that no item remains.

    An expired item can reappear if TTL is disabled before background deletion finishes.

  10. In Data Explorer, create a new container named ttl-demo in the existing cosmicworks database. Use /categoryId as the partition key and dedicated autoscale throughput with a maximum of 1,000 RU/s. If that name already exists, use a new, unused name for this test.

  11. Open the new container’s Scale and Settings. Set Time to Live to On, enter 60 seconds, and select Save.

  12. In the new container, add this item without a ttl property:

     {
       "id": "temp-record-001",
       "categoryId": "4F34E180-384D-42FC-AC10-FEC30227577F",
       "name": "Temporary record"
     }
    

    In this disposable container, every item without its own ttl expires 60 seconds after its last modification.

  13. Open the context menu for the new container and select New SQL Query. Confirm that the query tab belongs to that container, then run SELECT * FROM c WHERE c.id = "temp-record-001". Wait about 90 seconds, then run it again. The item no longer appears because it inherits the container’s default TTL.

  14. Delete only the disposable ttl-demo container, or the alternative name you used, to stop its throughput charges. Keep product and the other shared lab containers.

  15. In product, confirm that Time to Live is Off, the temporary-item query returns no result, and SELECT VALUE COUNT(1) FROM c returns 295 before reusing this catalog.

Clean up resources

When you finish the course, delete the resource group only if you created it and every resource in it can be removed. If your lab provided ResourceGroup1, skip this command and delete only the exercise resources you no longer need:

az group delete --name $resourceGroup --yes --no-wait

If your lab environment provided the resource group, delete only the Azure Cosmos DB account instead:

az cosmosdb delete --name <your-account-name> --resource-group $resourceGroup --yes