Azure

Azure Cosmos DB: Choosing the Right NoSQL Solution

Azure Cosmos DB: Choosing the Right NoSQL Solution

"lineItems": [ {"sku":"A100","qty":2}, {"sku":"B200","qty":1} ],
"total": 149.50,
"_ttl": 604800
}

Architecture Overview: Partition Key Choice: tenantId (predictable distribution, natural access boundary). Avoid low cardinality (e.g. status).

az cosmosdb create
--name acct-biz-global
--resource-group rg-data-platform
--locations regionName=eastus failoverPriority=0 isZoneRedundant=false
--locations regionName=westeurope failoverPriority=1 isZoneRedundant=false
--default-consistency-level Session

az cosmosdb sql database create
--account-name acct-biz-global
--resource-group rg-data-platform
--name ordersdb

az cosmosdb sql container create
--account-name acct-biz-global
--resource-group rg-data-platform
--database-name ordersdb
--name orders
--partition-key-path /partitionKey
--throughput 400


**Expected output:**

```text
{ "documentEndpoint": "https://cosmos-myapp.documents.azure.com:443/", "provisioningState": "Succeeded" }

Terminal output for az cosmosdb create

Step 4: Indexing Policy

Disable indexing for large rarely queried sub-objects to save RU:

{
  "indexingMode": "consistent",
  "includedPaths": [ { "path": "/*" } ],
  "excludedPaths": [ { "path": "/lineItems/*" } ]
}

Update with SDK (.NET):

var containerProperties = new ContainerProperties("orders", "/partitionKey")
{
```text
IndexingPolicy = new IndexingPolicy
{
    Automatic = true,
    IndexingMode = IndexingMode.Consistent,
    IncludedPaths = { new IncludedPath { Path = "/*" } },
    ExcludedPaths = { new ExcludedPath { Path = "/lineItems/*" } }
}```
};
await database.CreateContainerIfNotExistsAsync(containerProperties, throughput: 400);

Step 5: CRUD & Bulk Operations (.NET)

var client = new CosmosClient(endpoint, key, new CosmosClientOptions { AllowBulkExecution = true });


var container = client.GetContainer("ordersdb", "orders");

// Create
await container.CreateItemAsync(order, new PartitionKey(order.partitionKey));

// Read
var response = await container.ReadItemAsync<Order>(order.id, new PartitionKey(order.partitionKey));

// Query
var q = new QueryDefinition("SELECT c.id, c.status, c.total FROM c WHERE c.partitionKey = @tenant AND c.status = @status")
```text
.WithParameter("@tenant", tenantId)
.WithParameter("@status", "Pending");```
var iterator = container.GetItemQueryIterator<OrderSummary>(q, requestOptions: new QueryRequestOptions{ PartitionKey = new PartitionKey(tenantId) });
while(iterator.HasMoreResults){ var page = await iterator.ReadNextAsync(); }

// Bulk
var tasks = ordersToInsert.Select(o => container.CreateItemAsync(o, new PartitionKey(o.partitionKey)));
await Task.WhenAll(tasks);

Step 6: Security

  • Use Managed Identity for server-side compute (Functions / App Service) — no keys in code.
  • Store connection secrets in Key Vault for bootstrap scenarios only.
  • Private Endpoints to restrict public exposure.
  • Firewall: Allow only required subnets.
  • RBAC: Assign Cosmos DB Account Reader for monitoring roles; custom role definitions for limited container access.

Step 7: Monitoring & Alerts

Core Metrics:

  • Total Request Units Consumed
  • Normalized RU per partition (detect hotspots)
  • Throttled Requests (HTTP 429)
  • Server-side latency (Data plane) & Consistency latency

Sample Alert (CLI):

az monitor metrics alert create \
  --name cosmos-ru-burst \
  --resource-group rg-data-platform \
  --scopes "/subscriptions/$SUB/resourceGroups/rg-data-platform/providers/Microsoft.DocumentDB/databaseAccounts/acct-biz-global" \
  --condition "max TotalRequestUnits > 50000" \
  --window-size 5m \
  --evaluation-frequency 1m \
  --action-group "/subscriptions/$SUB/resourceGroups/rg-data-platform/providers/microsoft.insights/actionGroups/ag-oncall"

Expected output:

{ "value": [{ "name": { "value": "Requests" }, "timeseries": [{ "data": [{ "total": 1234 }] }] }] }

Terminal output for az monitor

Step 8: Cost Optimization

Strategy Description RU Impact Notes
Autoscale Scale 10x on demand Efficient burst Set max RU carefully
Analytical Store Isolate HTAP queries Removes RU overhead from analytics Enable per container
TTL Remove stale docs Frees storage & index Use _ttl on item
Excluded Paths Skip indexing rarely queried fields Lowers write RU Validate query patterns
Caching (Redis) Offload hot reads Reduces RU read Cache by partitionKey + id
Batch Writes Group operations Reduces network overhead Use bulk execution

Step 9: Backup & DR

  • Cosmos DB continuous backup (point-in-time restore) for mission-critical workloads.
  • Multi-region writes only if global active-active needed; otherwise single write region + failover region.
  • Periodically rehearse failover using CLI az cosmosdb failover-priority-change (non-prod first).

Step 10: Troubleshooting

Symptom Cause Action Resolution
High RU spikes Inefficient queries (SELECT *) Enable query metrics Add projections & excluded paths
Hot partition Skewed partition key Inspect per-partition RU Redesign key or introduce synthetic key
Frequent 429 RU under-provisioned Monitor throttled metric Increase throughput or optimize indexing
Latency increase Cross-region reads + Strong Review consistency Downgrade to Session where safe
High storage cost Orphaned stale items Enable TTL Set TTL & archive essentials

Best Practices

  • Prefer Session consistency for balanced latency & correctness.
  • Model around logical access boundary (tenant, customer) for partition key.
  • Project only required JSON attributes; exclude large arrays from indexing.
  • Use autoscale for spiky workloads; fixed RU for steady predictable traffic.
  • Instrument every SDK call with latency + RU diagnostics.
  • Maintain IaC definitions (Bicep/Terraform) for repeatable environments.

Best Practices

Best Practices

Common Issues & Troubleshooting

Issue: Hot partitions
Solution: Redesign partition key; consider hierarchical (tenantId+month) to spread writes.

Common Issues & Troubleshooting

Common Issues & Troubleshooting

Issue: Many 429 errors during peak hour
Solution: Implement retry with jitter; evaluate autoscale max RU or pre-warm.

Issue: Query RU cost unexpectedly high
Solution: Use SET CROSS_PARTITION only when necessary; add filters on partition key.

Architecture Decision and Tradeoffs

When designing cloud infrastructure solutions with Azure, consider these key architectural trade-offs:

Approach Best For Tradeoff
Managed / platform service Rapid delivery, reduced ops burden Less customisation, potential vendor lock-in
Custom / self-hosted Full control, advanced tuning Higher operational overhead and cost

Recommendation: Start with the managed approach for most workloads and move to custom only when specific requirements demand it.

Validation and Versioning

  • Last validated: April 2026
  • Validate examples against your tenant, region, and SKU constraints before production rollout.
  • Keep module, CLI, and SDK versions pinned in automation pipelines and review quarterly.

Security and Governance Considerations

  • Apply least-privilege access using RBAC roles and just-in-time elevation for admin tasks.
  • Store secrets in managed secret stores and avoid embedding credentials in scripts or source files.
  • Enable audit logging, data protection policies, and periodic access reviews for regulated workloads.

Cost and Performance Notes

  • Define budgets and alerts, then monitor usage and cost trends continuously after go-live.
  • Baseline performance with synthetic and real-user checks before and after major changes.
  • Scale resources with measured thresholds and revisit sizing after usage pattern changes.

Official Microsoft References

Public Examples from Official Sources

Key Takeaways

  • Partition key & consistency model decisions dominate performance outcomes.
  • Indexing policy tuning prevents runaway RU costs.
  • Observability (metrics + alerts) enables proactive scaling & reliability.
  • Autoscale + TTL + exclusion paths form core cost optimization triad.

Key Takeaways

Key Takeaways

Next Steps

  • Add analytical store and Synapse link for HTAP scenarios.
  • Introduce Redis cache for top partition read patterns.
  • Expand global replication (APAC) with latency measurements.

Additional Resources


What data modeling challenge are you facing with Cosmos DB? Share below!
```

AI Assistant
AI Assistant

Article Assistant

Ask me about this article

AI
Hi! I'm here to help you understand this article. Ask me anything about the content, concepts, or implementation details.