Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 14

Choosing the Right Partition Key

Recommended resources

Welcome back! In our previous lesson, we explored the five consistency levels in Azure Cosmos DB and the critical trade-offs they represent. We learned that your choice of consistency level is a fundamental decision that impacts performance, availability, and data durability.

Today, we'll dive into the second pillar of Cosmos DB architecture: partitioning. This is the mechanism that allows Cosmos DB to scale horizontally to handle virtually unlimited amounts of data and throughput. This lesson directly addresses the learning outcome: Evaluate partitioning strategies and select an appropriate partition key for a given scenario. Understanding how to choose a good partition key is one of the most important skills for a developer working with Cosmos DB, as it has a profound impact on performance, cost, and scalability.

1. Why Partition? The Key to Unlimited Scale

Coming from a background with traditional relational databases like SQL Server, you're likely familiar with "scaling up"—upgrading to a more powerful server with more CPU and RAM to handle increased load. Cosmos DB, designed for cloud-native applications, uses a different approach: "scaling out" or horizontal scaling.

Instead of making one machine bigger, Cosmos DB distributes your data and workload across many smaller, commodity machines. This concept is similar to how a modern web application might be load-balanced across multiple web servers instead of running on a single, massive one. This distribution is what we call partitioning.

To see why this is so essential, let's watch a brief segment from the "Azure Cosmos DB Essentials" series.

Partition Strategy | Azure Cosmos DB Essentials Season 2

This video introduces the core concept of partitioning as the foundation for scaling in a distributed database like Cosmos DB.

Please watch the first two sections: The motivation for partitioning, which explains the scale-out model. The role of the partition key, which introduces it as a "placement hint" and contrasts efficient queries with inefficient "fan-out" queries.

As the video explained, the partition key is the property in your JSON documents that Cosmos DB uses to determine which underlying machine to store your data on. When you write a new item, Cosmos DB uses the partition key value to route the data to the correct location. When you query data and provide the partition key in your filter, Cosmos DB can go directly to the right machine, which is extremely efficient. A query that doesn't include the partition key must "fan out" to all machines, which consumes more Request Units (RUs) and increases latency, especially as your container grows.


2. Logical vs. Physical Partitions

To understand partitioning correctly, it's crucial to distinguish between logical and physical partitions. As a developer, you only ever interact with logical partitions; Azure manages the physical ones entirely.

  • Logical Partition: A group of items that all have the same partition key value. For example, if you partition a Users container by country, all users from "South Africa" would belong to one logical partition. Each logical partition has a storage limit of 20 GB.
  • Physical Partition: An internal, underlying unit of compute and storage (an SSD-backed replica set) that hosts your data. A single physical partition can hold one or more logical partitions. Each physical partition provides up to 10,000 RU/s of throughput and 50 GB of storage.

This distinction is important: you can have millions of logical partitions, which is perfectly fine and often desirable. Cosmos DB will map these logical partitions across a much smaller, appropriate number of physical partitions behind the scenes. As your data and throughput needs grow, Cosmos DB automatically splits physical partitions and redistributes your logical partitions without any downtime.

The following video provides an excellent visual explanation of this relationship.

Partitioning: Choosing the right key for cost and performance ​with Azure Cosmos DB

This video from the Azure Cosmos DB team clearly differentiates between logical and physical partitions.

Watch from Logical vs. Physical to understand the definitions and the relationship between them. Continue watching from the visual explanation to see how Cosmos DB uses a hash of the partition key to map data to a physical partition.

The key takeaway is that your goal is to choose a partition key that creates many logical partitions, allowing Cosmos DB to distribute them evenly across the underlying physical partitions.

This diagram illustrates how a container is divided into logical partitions based on the partition key. These logical partitions are then managed within physical partitions, which are replicated globally for high availability and low latency.

3. Characteristics of a Good Partition Key

Selecting your partition key is a critical design decision you make when you create a container, and it cannot be changed later without migrating the data. An effective partition key will lead to a scalable, performant, and cost-effective solution.

The Microsoft Learn documentation provides the definitive checklist for what makes a good partition key.

Partitioning and horizontal scaling - Azure Cosmos DB

This section of the official documentation outlines the essential criteria for selecting a partition key.

Please read the section titled Choose a partition key. Focus on the bulleted list of criteria that a partition key should meet for all containers.

To summarize those crucial points, a good partition key should:

  • Have high cardinality: The property should have a wide range of possible values. A property like userId or deviceId is a great candidate. A property like orderStatus with only a few values ("pending", "shipped", "delivered") would be a terrible choice.
  • Distribute workload evenly: The key should spread both data storage and requests (RUs) evenly across all logical partitions. This prevents "hot partitions"—a situation where one logical partition receives a disproportionate amount of traffic, exhausting its throughput limit while other partitions sit idle.
  • Be immutable: The value of the partition key property for an item cannot be updated. You would have to delete and re-insert the item to change it.
  • Align with query patterns (for read-heavy workloads): If your application primarily reads data, choosing a key that you frequently use as a filter in your queries will result in highly efficient "in-partition" queries.

4. Evaluating Partitioning Strategies for Common Scenarios

Now let's apply these principles. The best partitioning strategy depends heavily on your application's workload, primarily whether it's read-heavy or write-heavy.

Strategy 1: Optimizing for Read-Heavy Workloads

In a read-heavy workload (e.g., a product catalog, user profiles, a blogging platform), the primary goal is to make your most frequent queries as fast and cheap as possible. This is achieved by ensuring those queries are in-partition queries.

Let's see a practical demo of the performance difference.

Partitioning: Choosing the right key for cost and performance ​with Azure Cosmos DB

This demo shows the dramatic impact of choosing the right partition key for a read-heavy retail scenario.

Watch the section from the read-heavy demo. The presenter queries for product reviews written by a specific user. Notice the huge difference in RU cost when the container is partitioned by id (a bad choice for this query) versus username (a good choice).

As the demo showed, partitioning by username reduced the query cost by nearly 3x. This is because when you filter by username, Cosmos DB knows exactly which logical (and therefore physical) partition to query. When partitioned by id, it has to perform a costly fan-out query across all physical partitions.

Guideline for Read-Heavy: Analyze your most frequent SELECT ... WHERE clauses. The property you filter on most often is an excellent candidate for your partition key.

Strategy 2: Optimizing for Write-Heavy Workloads

In a write-heavy workload (e.g., IoT telemetry, logging, real-time analytics), the primary goal is to distribute incoming writes as evenly as possible to maximize throughput and avoid hot partitions.

Let's look at another demo, this time with an IoT scenario.

Partitioning: Choosing the right key for cost and performance ​with Azure Cosmos DB

This demo simulates a write-heavy IoT workload and highlights the "hot partition" problem.

Watch the section from the write-heavy demo. Pay attention to what happens when date is used as the partition key. All writes for the current day go to the same logical partition, creating a massive bottleneck. Then, see how using a high-cardinality key (vehicleId) distributes the load and achieves much higher throughput.

This demo perfectly illustrates why a high-cardinality key is essential for write-heavy workloads. Using vehicleId ensures that data from different vehicles is sent to different logical partitions, allowing Cosmos DB to use the full provisioned throughput across all its physical partitions.

Strategy 3: Using a Synthetic Partition Key

What if no single property in your document is a good partition key?

  • You might have a high-cardinality key, but your queries filter on something else.
  • Your ideal key might lead to a logical partition exceeding the 20 GB limit (e.g., a single IoT device sending data for years).

In these cases, you can create a synthetic partition key by combining multiple properties into a new, single property. The IoT demo hinted at this by suggesting a key like vehicleId_currentDate. This approach still provides high cardinality for writes (distributing by vehicle) while also helping to bound the size of any single logical partition over time (since vehicleId_2024-10-26 is a different partition from vehicleId_2024-10-27).

For a concise summary of these strategies, the Microsoft Learn documentation provides an excellent table.

Partitioning and horizontal scaling - Azure Cosmos DB

This table provides a summary of different partitioning strategies and when to use them.

Review the table in the section titled Types of partition keys. Focus on the descriptions for Regular Partition Key and Synthetic Partition Key. The other types (Hierarchical, GSI) are more advanced, but it's good to be aware of them.


Conclusion

We've covered a lot of ground on the most important design decision you'll make with Cosmos DB. Choosing the right partition key from the start is essential for building a scalable and cost-effective application.

Here are the key takeaways:

  • Partitioning is how Cosmos DB scales out to provide massive throughput and storage.
  • You choose a partition key to create logical partitions, which Azure maps to physical partitions.
  • A good partition key has high cardinality and distributes requests and data evenly.
  • For read-heavy workloads, choose a key that aligns with your most common query filters to enable efficient in-partition queries.
  • For write-heavy workloads, choose a high-cardinality key (like id or deviceId) to avoid hot partitions and maximize write throughput.
  • When no single property works well, a synthetic key can be created by combining multiple properties.

In our next lesson, we'll finally get hands-on. We'll take what we've learned about consistency and partitioning and apply it as we learn how to create a Cosmos DB account, database, and container programmatically using the .NET SDK. You'll see exactly where the partition key is specified during the creation process.