Selecting the right partition key in Azure Cosmos DB is one of the most critical decisions you will make when designing your database schema. Pick the wrong key, and you will hit performance bottlenecks due to unbalanced workload distribution across logical partitions.
What Makes a Good Partition Key?
A strong partition key distributes reads and writes evenly across physical storage partitions. Ideally, your chosen key should have high cardinality—meaning it has thousands or millions of distinct values—and distribute Request Units (RU) evenly across your workload.
- High Cardinality: Choose properties like
userId,deviceId, ororderIdrather than low-cardinality fields likegenderorstatus. - Balanced Read/Write Pattern: Ensure that no single partition key value absorbs 80% of your total request volume, which causes hot partitions.
- Synthetic Keys: Combine multiple properties (e.g.,
tenantId_date) when no single field meets cardinality requirements.
Configuring Partition Keys via the .NET SDK
Here is how you define container settings and write items with explicit partition key specifications using C#:
// Initialize container properties specifying the partition key JSON path
ContainerProperties containerProperties = new ContainerProperties(
id: "Orders",
partitionKeyPath: "/customerId"
);
// Create the container if it does not already exist with provisioned throughput
Container container = await database.CreateContainerIfNotExistsAsync(containerProperties, throughput: 400);
// Define a record object to persist
var order = new Order
{
id = Guid.NewGuid().ToString(),
customerId = "CUST_98234",
totalAmount = 149.99m
};
// Perform point write operation by supplying item and partition key value
ItemResponse<Order> response = await container.CreateItemAsync<Order>(
item: order,
partitionKey: new PartitionKey(order.customerId)
);By ensuring point operations use the exact partition key value, Cosmos DB routes the request directly to the target partition without querying across physical boundaries.
Choosing a partition key in Azure Cosmos DB affects query cost, workload balance, and how easily your application can grow. The best choice usually comes from looking at how the application reads and writes data—not just which field has the most values.
Start with your query patterns
List the reads the application performs most often. If a request can specify the partition key, Cosmos DB can target a logical partition instead of searching across the container. For example, if most requests fetch orders for one customer,
customerIdmay be a better fit than a field used only in occasional reports. Point reads are especially efficient when the application knows both the item ID and its partition key.Check distribution and growth
A useful key has many possible values and spreads storage and traffic reasonably evenly. A low-cardinality field such as
statuscan concentrate data and requests. A key with plenty of distinct values can still be a poor choice if most traffic lands on one value—for instance, a very large tenant in an otherwise quiet multi-tenant container.Think about future data volume and request spikes, not just the current dataset. A high-cardinality partition key helps avoid oversized or heavily accessed logical partitions, but only if the workload actually uses those values across its requests.
Keep related operations together when needed
Transactions and transactional batches are scoped to a single logical partition. If the application must update several related items atomically, choose a key that puts those items together. This can create a trade-off: a key that suits transactional batch partition scope may concentrate traffic, so weigh that against the distribution requirements.
For multi-tenant container design, a tenant key can make tenant-scoped queries straightforward. If tenants vary greatly in size or traffic, consider whether a single tenant value could become a hotspot. Hierarchical partition keys may help when access commonly follows multiple levels, such as tenant and user, but check that the hierarchy matches real query patterns.
A practical test before committing
Test candidate keys with representative query and traffic patterns. A partition key path is fixed when you create a container, so changing it later generally means creating another container and migrating the data. That makes a small design test worthwhile before production.
Understanding Cosmos DB Partitioning
Azure Cosmos DB scales horizontally by distributing data across physical partitions. Data is logically grouped into logical partitions based on the value of your chosen partition key. Pick a poor key, and you will hit performance bottlenecks, throttled requests (429 errors), and inflated Request Unit (RU) costs.
Key Criteria for Selecting a Partition Key
To keep your database fast and cost-effective, target these core principles:
userId,deviceId, ororderId). Avoid properties with few distinct values likegenderorstatus.WHEREclause. Queries scoped to a single logical partition consume significantly fewer RUs than cross-partition queries that fan out across every physical partition.Using Synthetic Partition Keys
When no single property meets the criteria for high cardinality and even distribution, combine multiple properties into a synthetic partition key. For example, in an IoT application receiving millions of telemetry events, partitioning by
deviceIdalone might cause a hot partition if one device generates far more data than others.Combining
deviceIdand a formatted date string creates a balanced synthetic key likeDEVICE123_2026-03-30.Provisioning Containers with a Partition Key Path
When initializing your container using the .NET SDK, specify the exact JSON path corresponding to your partition key.
Common Partitioning Pitfalls to Avoid