Generated banner for Cosmosdb Best Practices
Generated logo for Cosmosdb Best Practices

Cosmosdb Best Practices

ClineOfficialCreated by cosmosdb-agent-kitDistributed by Cline

  • Skill
  • Guidelines
  • Software development
  • MIT
  • No issues found

From the author

Azure Cosmos DB performance optimization and best practices guidelines for NoSQL, partitioning, queries, SDK usage, and vector search. Use when writing, reviewing, or refactoring code that interacts with Azure Cosmos DB, designing data models, optimizing queries, or implementing high-performance database operations.
— the description by cosmosdb-agent-kit

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured set of 73+ guidelines for working with Azure Cosmos DB. It covers essential topics including data modeling, partition key design, query optimization, SDK usage, indexing, throughput scaling, global distribution, monitoring, design patterns, and vector search. The content is organized into modular rule files to assist developers in writing, reviewing, and refactoring code that interacts with the database.

What it does

  • Provides specific rules for designing efficient data models and choosing partition keys.
  • Offers guidance on optimizing queries and implementing SDK patterns.
  • Details strategies for indexing, throughput management, and global distribution.
  • Includes best practices for implementing vector search and RAG patterns.
  • Supplies diagnostic and monitoring recommendations for database operations.
  • Organizes content into categorized rule files for targeted retrieval.

When to use it

  • When designing data models or selecting partition keys for Cosmos DB.
  • When writing or refactoring application code that uses the Cosmos DB SDK.
  • When optimizing query performance or indexing strategies.
  • When configuring global distribution, throughput, or scaling settings.
  • When implementing vector search or advanced design patterns.

Advantages

  • Modular structure allows for loading only relevant rules for specific tasks.
  • Covers a wide range of operational and architectural concerns.
  • Provides clear examples of incorrect and correct implementation patterns.
  • Prioritizes rules by impact to guide development decisions.

Usage examples

“How should I choose a partition key for my Cosmos DB container?”
The agent will retrieve rules from the partition- prefix to explain high-cardinality, write distribution, and query alignment.
“What are the best practices for using the Cosmos DB SDK?”
The agent will load rules from the sdk- prefix to provide guidance on singleton client usage, async APIs, and retry logic.
“How do I optimize my data model for read-heavy workloads?”
The agent will reference model- prefixed rules to explain denormalization and embedding strategies.
“What should I consider when implementing vector search in Cosmos DB?”
The agent will access vector- prefixed rules to explain embedding policies, index types, and similarity search functions.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/cline/cosmosdb-best-practices/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip cosmosdb-best-practices.zip -d .agents/skills

Documentation by cosmosdb-agent-kit

Azure Cosmos DB Best Practices

Comprehensive performance optimization guide for Azure Cosmos DB applications, containing 73+ rules across 10 categories, prioritized by impact to guide automated refactoring and code generation.

73 individual rule files are in the rules/ directory, one file per rule, synced from the AzureCosmosDB/cosmosdb-agent-kit. Load only the relevant rule file(s) when answering a question — do NOT load all files at once.

When to Apply

Reference these guidelines when:

  • Designing data models for Cosmos DB

  • Choosing partition keys

  • Writing or optimizing queries

  • Implementing SDK patterns

  • Reviewing code for performance issues

  • Configuring throughput and scaling

  • Building globally distributed applications

  • Implementing vector search and RAG patterns

Rule Index

Rules are grouped by category prefix. For a given question, load files matching the relevant prefix (e.g., model-*.md for data modeling, sdk-*.md for SDK usage). See rules/_sections.md for category descriptions.

1. Data Modeling — CRITICAL (prefix: model-)
2. Partition Key Design — CRITICAL (prefix: partition-)
3. Query Optimization — HIGH (prefix: query-)
4. SDK Best Practices — HIGH (prefix: sdk-)
5. Indexing Strategies — MEDIUM-HIGH (prefix: index-)
6. Throughput & Scaling — MEDIUM (prefix: throughput-)
7. Global Distribution — MEDIUM (prefix: global-)
8. Monitoring & Diagnostics — LOW-MEDIUM (prefix: monitoring-)
9. Design Patterns — HIGH (prefix: pattern-)
10. Vector Search — HIGH (prefix: vector-)

How to Use

Each rule is a separate file under rules/. When answering a Cosmos DB question, read only the relevant rule file(s) based on the prefix matching the topic:

  • Data modeling question → read rules/model-*.md files

  • Partition key question → read rules/partition-*.md files

  • SDK/client question → read rules/sdk-*.md files

  • etc.

Each rule file contains:

  • Brief explanation of why it matters

  • Incorrect code example with explanation

  • Correct code example with explanation

  • Additional context and references

Source: AzureCosmosDB/cosmosdb-agent-kit

Files

rules/sdk-etag-concurrency.md


title: Use ETags for optimistic concurrency on read-modify-write operations impact: HIGH impactDescription: prevents lost updates in concurrent write scenarios tags: sdk, concurrency, etag, consistency, read-modify-write

Use ETags for Optimistic Concurrency

When performing read-modify-write operations (read a document, update a field, write it back), always use ETags to prevent lost updates from concurrent writes. Without ETags, the last writer silently overwrites changes from other operations.

Problem: Lost updates without ETag checks

// Anti-pattern: Read-modify-write without concurrency control
// If two requests run concurrently, one update is silently lost
public async Task UpdatePlayerStatsAsync(string playerId, int newScore)
{
    // Thread A reads player (bestScore: 100)
    var response = await _container.ReadItemAsync<Player>(
        playerId, new PartitionKey(playerId));
    var player = response.Resource;

    // Thread B also reads player (bestScore: 100)
    // Thread B updates bestScore to 200 and writes

    // Thread A updates bestScore to 150 and writes
    // Thread A's write OVERWRITES Thread B's update!
    player.BestScore = Math.Max(player.BestScore, newScore);
    player.TotalGamesPlayed++;
    player.TotalScore += newScore;
    player.AverageScore = player.TotalScore / player.TotalGamesPlayed;

    await _container.UpsertItemAsync(player,  // Overwrites without checking!
        new PartitionKey(playerId));
}

Solution: ETag-based optimistic concurrency with retry

// Correct: Use ETag to detect concurrent modifications and retry
public async Task UpdatePlayerStatsAsync(string playerId, int newScore)
{
    const int maxRetries = 3;

    for (int attempt = 0; attempt < maxRetries; attempt++)
    {
        try
        {
            // Read current state (includes ETag in response headers)
            var response = await _container.ReadItemAsync<Player>(
                playerId, new PartitionKey(playerId));
            var player = response.Resource;
            var etag = response.ETag;  // Capture the ETag

            // Modify the document
            player.BestScore = Math.Max(player.BestScore, newScore);
            player.TotalGamesPlayed++;
            player.TotalScore += newScore;
            player.AverageScore = player.TotalScore / player.TotalGamesPlayed;
            player.LastPlayedAt = DateTime.UtcNow;

            // Write with ETag condition — fails if document changed since read
            await _container.UpsertItemAsync(player,
                new PartitionKey(playerId),
                new ItemRequestOptions
                {
                    IfMatchEtag = etag  // Only succeeds if ETag matches
                });

            return; // Success
        }
        catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PreconditionFailed)
        {
            // HTTP 412: Document was modified by another request
            // Retry by re-reading the latest version
            if (attempt == maxRetries - 1)
            {
                throw new InvalidOperationException(
                    $"Failed to update player {playerId} after {maxRetries} attempts due to concurrent modifications.", ex);
            }
            // Loop back to re-read and retry
        }
    }
}

Java equivalent:

// Java SDK: Use ETag with ifMatchETag option
CosmosItemResponse<Player> response = container.readItem(
    playerId, new PartitionKey(playerId), Player.class);
Player player = response.getItem();
String etag = response.getETag();

// Modify player...

CosmosItemRequestOptions options = new CosmosItemRequestOptions();
options.setIfMatchETag(etag);  // Conditional write

try {
    container.upsertItem(player, new PartitionKey(playerId), options);
} catch (CosmosException ex) {
    if (ex.getStatusCode() == 412) {
        // Retry: document was modified concurrently
    }
}

Python equivalent:

# Python SDK: Use ETag with MatchConditions from azure.core
from azure.core import MatchConditions
from azure.cosmos.exceptions import CosmosHttpResponseError

response = container.read_item(item=player_id, partition_key=player_id)
etag = response.get('_etag')

# Modify response dict...

try:
    container.upsert_item(
        body=response,
        etag=etag,
        match_condition=MatchConditions.IfNotModified  # NOT a string, must be enum
    )
except CosmosHttpResponseError as e:
    if e.status_code == 412:
        # Retry: document was modified concurrently
        pass

⚠️ Python SDK Pitfall: match_condition must be MatchConditions.IfNotModified from azure.core, not a string like "IfMatch". Passing a string raises TypeError: Invalid match condition. The MatchConditions enum values are: IfNotModified, IfModified, IfPresent, IfMissing.

When to use ETags:

  • Always use for read-modify-write patterns (counters, aggregates, status updates)

  • Always use when multiple users/services can modify the same document

  • Always use when updating denormalized data (see below)

  • Skip for append-only operations (new document creation with unique IDs)

  • Skip for idempotent overwrites where last-writer-wins is acceptable

⚠️ Critical: ETags for Denormalized Data Updates

Denormalized fields (e.g., task counts on a project, user names on related documents) are especially vulnerable to lost updates. When multiple operations update the same parent document's counters concurrently, ETag checks are mandatory:

// ❌ Anti-pattern: Updating denormalized counts without ETag
public void updateProjectTaskCounts(String tenantId, String projectId) {
    // Two tasks created simultaneously — both read count=5
    CosmosItemResponse<Project> response = container.readItem(
        projectId, partitionKey, Project.class);
    Project project = response.getItem();
    
    project.setTaskCountTotal(countTasksInProject(tenantId, projectId)); // = 7
    container.upsertItem(project, partitionKey, null);
    // Second concurrent call also sets count to 7, missing the other's task!
}

// ✅ Correct: ETag-protected denormalized count update with retry
public void updateProjectTaskCounts(String tenantId, String projectId) {
    for (int attempt = 0; attempt < 3; attempt++) {
        try {
            CosmosItemResponse<Project> response = container.readItem(
                projectId, partitionKey, Project.class);
            Project project = response.getItem();
            String etag = response.getETag();

            // Re-count from source of truth
            project.setTaskCountTotal(countTasksInProject(tenantId, projectId));
            project.setTaskCountOpen(countTasksByStatus(tenantId, projectId, "open"));

            CosmosItemRequestOptions options = new CosmosItemRequestOptions();
            options.setIfMatchETag(etag);  // Fail if another update landed
            container.upsertItem(project, partitionKey, options);
            return;
        } catch (CosmosException ex) {
            if (ex.getStatusCode() == 412 && attempt < 2) continue; // Retry
            throw ex;
        }
    }
}

Why denormalized data is high-risk:

  • Multiple child operations (create task, delete task, update status) all touch the same parent

  • Without ETag checks, concurrent operations silently overwrite each other's count updates

  • The resulting counts become permanently incorrect until manually recalculated

  • This is the most common source of data inconsistency in Cosmos DB applications

Key Points:

  • Every Cosmos DB document has a system-managed _etag property that changes on every write

  • Pass IfMatchEtag (or setIfMatchETag in Java) to get HTTP 412 on conflicts

  • Always implement retry logic (typically 3 attempts) for ETag conflicts

  • ETag checks add no extra RU cost — it's a header comparison, not an additional read

  • For high-contention scenarios (thousands of concurrent updates to same document), consider a different data model (e.g., append scores as separate documents, aggregate periodically)

Reference: Optimistic concurrency control in Azure Cosmos DB

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
cosmosdb-agent-kit
Publisher
Cline (Official)
Distributed by
Cline
Source
cline/skills · skills/cosmosdb-best-practices · commit 2637846
Licence
MIT License (redistribution allowed)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by cosmosdb-agent-kit or Cline.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download cosmosdb-best-practices.zip