Cosmos DB powers low-latency, elastic workloads, but only if you model partitions and RUs correctly.
Azure Cosmos DB is a managed, globally distributed NoSQL database with single-digit millisecond reads. It offers several APIs; NoSQL (JSON documents queried with a SQL-like language) is the native one, with MongoDB, Cassandra, Gremlin and Table APIs for compatibility.
Resource model: account (endpoint, regions, consistency) > database > container (holds items, has a partition key and indexing policy) > item (a JSON document with an id).
Every container has a partition key, a property such as /customerId. Items with the same value form a logical partition (limit 20 GB); Cosmos spreads logical partitions over physical partitions to scale. The id is unique only within its partition, so a point read needs both id and partition key and is the cheapest operation.
Cost is measured in request units (RU): a 1 KB point read is 1 RU; writes and queries cost more. You pay for provisioned throughput (manual or autoscale RU/s) or use serverless for intermittent traffic. Requests above your RU/s get HTTP 429 and must be retried (the SDKs do it for you).
All properties are indexed by default; tune the indexing policy to exclude paths you never filter on, which lowers write RU. Data-plane access with Entra ID uses Cosmos DB's own data-plane roles, assigned with az cosmosdb sql role assignment create.
Example
# pip install azure-cosmos azure-identity
from azure.cosmos import CosmosClient, PartitionKey
from azure.identity import DefaultAzureCredential
client = CosmosClient("https://cosmos-orders.documents.azure.com:443/", DefaultAzureCredential())
db = client.get_database_client("shop")
orders = db.get_container_client("orders") # partition key: /customerId
orders.upsert_item({"id": "o-1001", "customerId": "c-42", "total": 59.90, "status": "paid"})
item = orders.read_item(item="o-1001", partition_key="c-42") # point read, ~1 RU
print(item["total"]) # 59.9
rows = orders.query_items(
"SELECT c.id, c.total FROM c WHERE c.customerId = @cid AND c.status = 'paid'",
parameters=[{"name": "@cid", "value": "c-42"}], partition_key="c-42")
print([r["id"] for r in rows]) # ['o-1001']Remember
- Account > database > container > item
- Partition key choice drives scale; a logical partition is capped at 20 GB
- Point reads (id + partition key) are the cheapest operation
- Throughput is RU/s; 429 means throttled, retry
Watch out for
- Querying without the partition key, which fans out to every physical partition and burns RUs.