|
| 1 | +--- |
| 2 | +title: Unlimited logical partition storage with hierarchical partition keys |
| 3 | +description: Learn how to use hierarchical partition keys with a unique last level to scale beyond the 20-GB logical partition limit in Azure Cosmos DB. |
| 4 | +author: lnajaroen |
| 5 | +ms.author: lnajaroen |
| 6 | +ms.service: azure-cosmos-db |
| 7 | +ms.topic: concept-article |
| 8 | +ms.date: 03/24/2026 |
| 9 | +ai-usage: ai-assisted |
| 10 | +appliesto: |
| 11 | + - ✅ NoSQL |
| 12 | +--- |
| 13 | + |
| 14 | +# Unlimited logical partition storage with hierarchical partition keys in Azure Cosmos DB |
| 15 | + |
| 16 | +This document explains how hierarchical partition keys (HPK) can help you model high-cardinality data. To avoid hitting the 20 GB logical partition size limit, use a multi-level partition key path that ends with a unique identifier, such as /id. |
| 17 | + |
| 18 | +In Azure Cosmos DB, items are grouped into logical partitions based on the value of the partition key. A single logical partition has a maximum storage size of 20 GB. For more information, see [logical partitions overview](partitioning.md). If your data model causes too many items to share the same partition key value (for example, all events for a single customer, tenant, device, or account), that logical partition can grow until it reaches the 20-GB limit, at which point writes targeting that partition fail. |
| 19 | + |
| 20 | +You can avoid this limit by using [hierarchical partition keys](hierarchical-partition-keys.md) (HPK) with a unique identifier as the final level. A unique identifier guarantees that the previous levels can exceed 20GB. For example, if the partition key hierarchy is TenantId, UserId, and id (guid), then you can have infinite data for each combination of TenantId, UserId. This strategy works with any HPK container — no extra account-level settings are required. |
| 21 | + |
| 22 | +## Best practice: use a unique last level |
| 23 | + |
| 24 | +Choose one to three business-grouping levels (such as tenant, customer, or workload) and use a unique final level of `/id`. Azure Cosmos DB uses the combined hierarchy to distribute items. |
| 25 | + |
| 26 | +For example, a multitenant application might use the following hierarchical partition key path: |
| 27 | + |
| 28 | +- `/tenantId` |
| 29 | +- `/userId` |
| 30 | +- `/id` |
| 31 | + |
| 32 | +With hierarchical partition keys, the logical partition key is defined as the full concatenation of all levels. In this example, each logical partition key is the combination of `tenantId` + `userId` + `id`. Because `id` is unique for every item, each logical partition contains at most one item and never approaches the 20-GB limit. This means the first and second levels (`tenantId` and `userId`) can individually exceed 20 GB of data, because their data is spread across many logical partitions defined by the full three-level key. |
| 33 | + |
| 34 | +You can apply this strategy today by creating a new container with an HPK path that ends with `/id`. For more information about creating containers with hierarchical partition keys, see [Create a container by using hierarchical partition keys](hierarchical-partition-keys.md#create-a-container-by-using-hierarchical-partition-keys). |
| 35 | + |
| 36 | +> [!IMPORTANT] |
| 37 | +> Adding a unique last level changes how you target point operations and transactional operations. Review the [prerequisites and limitations](#prerequisites-and-limitations) before you adopt this pattern. |
| 38 | +
|
| 39 | +## Prerequisites and limitations |
| 40 | + |
| 41 | +Before you adopt an HPK strategy that ends with a unique value of `/id`, make sure the pattern aligns with the transactional semantics your application requires. |
| 42 | + |
| 43 | +### Transactional operations |
| 44 | + |
| 45 | +Operations that require a single, shared partition key value across multiple items aren't compatible with a unique-last-level pattern. The following features are **not supported** when you use this pattern: |
| 46 | + |
| 47 | +- **Transactional batch (atomic batch):** Requires multiple items to share the same partition key value. |
| 48 | +- **Stored procedures and triggers:** Rely on grouping multiple items under one partition key value. |
| 49 | + |
| 50 | +If you need these features, consider an HPK design where the last level isn't unique, or use an alternative data model. Validate that your design still avoids exceeding the 20-GB logical partition limit for your workload. |
| 51 | + |
| 52 | +### Application requirements |
| 53 | + |
| 54 | +To use hierarchical partition keys, you must use a supported version of the Azure Cosmos DB SDK. See [supported SDK versions](hierarchical-partition-keys.md#get-started). |
| 55 | + |
| 56 | +## Optional: enforce the pattern at the account level |
| 57 | + |
| 58 | +The ability to exceed 20 GB on the first and second levels is built into hierarchical partition keys — it works automatically when you end your key path with a unique value like `/id`. No account-level property is required to get this benefit. |
| 59 | + |
| 60 | +However, if you want to **enforce** that all new containers created in an account follow this pattern, you can enable the `EnforceHierarchicalPartitionKeyIdLastLevel` property on your account. This property doesn't unlock new functionality — it prevents teams or applications from accidentally creating containers that don't use `/id` as the last level. |
| 61 | + |
| 62 | +> [!NOTE] |
| 63 | +> The minimum Resource Provider API version required is `2026-03-15`. For the full REST API specification, see [Database Accounts - Create Or Update](/rest/api/cosmos-db-resource-provider/database-accounts/create-or-update). |
| 64 | +
|
| 65 | +### Behavior after enablement |
| 66 | + |
| 67 | +| Behavior | Description | |
| 68 | +| --- | --- | |
| 69 | +| **New containers must use HPK + /id as last level** | Any new container created in the account must both use hierarchical partition keys and end with `/id` as the last level. If you want to partition only by `/id`, you can achieve this by setting `/id` as the first and only level in your hierarchical partition key. | |
| 70 | +| **Existing containers unchanged** | Enabling this property doesn't retroactively modify existing containers or their partition key configuration. To adopt this pattern for existing containers, create a new container with the desired HPK definition and [migrate your data](container-copy.md). | |
| 71 | +| **No defaulting of `/id`** | Azure Cosmos DB doesn't add `/id` as the last level automatically. You must specify the full HPK path at container creation time with `/id` as the last level. | |
| 72 | +| **Support for additional levels** | There is support for four levels of keys. However, a fourth level is recommended only for rare scenarios where three levels are needed in addition to `/id`. For the majority of workloads, two or three level of keys are sufficient to achieve good data distribution and optimize query performance. | |
| 73 | + |
| 74 | +## Enable and configure enforcement |
| 75 | + |
| 76 | +If you choose to enable the account-level enforcement, use one of the following methods to set the `EnforceHierarchicalPartitionKeyIdLastLevel` property on your account. |
| 77 | + |
| 78 | +### [Bicep](#tab/bicep) |
| 79 | + |
| 80 | +```bicep |
| 81 | +resource cosmosAccount 'Microsoft.DocumentDB/databaseAccounts@2026-03-15' = { |
| 82 | + name: '<account-name>' |
| 83 | + location: '<location>' |
| 84 | + properties: { |
| 85 | + databaseAccountOfferType: 'Standard' |
| 86 | + enableHierarchicalPartitionKeyIdLastLevel: true |
| 87 | + } |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +After you enable the property, create a container with a hierarchical partition key path that ends with `/id`: |
| 92 | + |
| 93 | +```bicep |
| 94 | +partitionKey: { |
| 95 | + paths: [ |
| 96 | + '/tenantId' |
| 97 | + '/userId' |
| 98 | + '/id' |
| 99 | + ] |
| 100 | + kind: 'MultiHash' |
| 101 | + version: 2 |
| 102 | +} |
| 103 | +``` |
| 104 | + |
| 105 | +### [ARM template](#tab/arm-json) |
| 106 | + |
| 107 | +```json |
| 108 | +{ |
| 109 | + "type": "Microsoft.DocumentDB/databaseAccounts", |
| 110 | + "apiVersion": "2026-03-15", |
| 111 | + "name": "<account-name>", |
| 112 | + "location": "<location>", |
| 113 | + "properties": { |
| 114 | + "databaseAccountOfferType": "Standard", |
| 115 | + "enableHierarchicalPartitionKeyIdLastLevel": true |
| 116 | + } |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +After you enable the property, create a container with a hierarchical partition key path that ends with `/id`: |
| 121 | + |
| 122 | +```json |
| 123 | +"partitionKey": { |
| 124 | + "paths": [ |
| 125 | + "/tenantId", |
| 126 | + "/userId", |
| 127 | + "/id" |
| 128 | + ], |
| 129 | + "kind": "MultiHash", |
| 130 | + "version": 2 |
| 131 | +} |
| 132 | +``` |
| 133 | + |
| 134 | +### [Azure CLI](#tab/azure-cli) |
| 135 | + |
| 136 | +```azurecli |
| 137 | +az cosmosdb update \ |
| 138 | + --resource-group <resource-group-name> \ |
| 139 | + --name <account-name> \ |
| 140 | + --enable-hierarchical-partition-key-id-last-level true |
| 141 | +``` |
| 142 | + |
| 143 | +### [PowerShell](#tab/powershell) |
| 144 | + |
| 145 | +```powershell |
| 146 | +Update-AzCosmosDBAccount ` |
| 147 | + -ResourceGroupName "<resource-group-name>" ` |
| 148 | + -Name "<account-name>" ` |
| 149 | + -EnableHierarchicalPartitionKeyIdLastLevel $true |
| 150 | +``` |
| 151 | + |
| 152 | +### [Management .NET SDK](#tab/net-v3) |
| 153 | + |
| 154 | +Use the `Azure.ResourceManager.CosmosDB` management SDK to enable the property on your account. |
| 155 | + |
| 156 | +```csharp |
| 157 | +using Azure.ResourceManager; |
| 158 | +using Azure.ResourceManager.CosmosDB; |
| 159 | +using Azure.ResourceManager.CosmosDB.Models; |
| 160 | + |
| 161 | +ArmClient client = new ArmClient(new DefaultAzureCredential()); |
| 162 | + |
| 163 | +ResourceIdentifier accountId = CosmosDBAccountResource.CreateResourceIdentifier( |
| 164 | + "<subscription-id>", "<resource-group-name>", "<account-name>"); |
| 165 | + |
| 166 | +CosmosDBAccountResource account = client.GetCosmosDBAccountResource(accountId); |
| 167 | + |
| 168 | +CosmosDBAccountPatch patch = new CosmosDBAccountPatch(); |
| 169 | +patch.EnableHierarchicalPartitionKeyIdLastLevel = true; |
| 170 | + |
| 171 | +await account.UpdateAsync(WaitUntil.Completed, patch); |
| 172 | +``` |
| 173 | + |
| 174 | +### [Management Java SDK](#tab/java-v4) |
| 175 | + |
| 176 | +Use the `azure-resourcemanager-cosmos` management SDK to enable the property on your account. |
| 177 | + |
| 178 | +```java |
| 179 | +import com.azure.resourcemanager.cosmos.CosmosManager; |
| 180 | +import com.azure.resourcemanager.cosmos.models.CosmosDBAccount; |
| 181 | + |
| 182 | +CosmosManager cosmosManager = CosmosManager.authenticate(credential, profile); |
| 183 | + |
| 184 | +CosmosDBAccount account = cosmosManager.databaseAccounts() |
| 185 | + .getByResourceGroup("<resource-group-name>", "<account-name>"); |
| 186 | + |
| 187 | +account.update() |
| 188 | + .withEnableHierarchicalPartitionKeyIdLastLevel(true) |
| 189 | + .apply(); |
| 190 | +``` |
| 191 | + |
| 192 | +### [Management Python SDK](#tab/python) |
| 193 | + |
| 194 | +Use the `azure-mgmt-cosmosdb` management SDK to enable the property on your account. |
| 195 | + |
| 196 | +```python |
| 197 | +from azure.identity import DefaultAzureCredential |
| 198 | +from azure.mgmt.cosmosdb import CosmosDBManagementClient |
| 199 | + |
| 200 | +credential = DefaultAzureCredential() |
| 201 | +client = CosmosDBManagementClient(credential, "<subscription-id>") |
| 202 | + |
| 203 | +account = client.database_accounts.get("<resource-group-name>", "<account-name>") |
| 204 | + |
| 205 | +update_params = { |
| 206 | + "location": account.location, |
| 207 | + "properties": { |
| 208 | + "enable_hierarchical_partition_key_id_last_level": True |
| 209 | + } |
| 210 | +} |
| 211 | + |
| 212 | +client.database_accounts.begin_create_or_update( |
| 213 | + "<resource-group-name>", "<account-name>", update_params |
| 214 | +).result() |
| 215 | +``` |
| 216 | + |
| 217 | +--- |
| 218 | + |
| 219 | +After you enable the property, create a new container by specifying a hierarchical partition key path that ends with `/id` (for example: `/tenantId`, `/userId`, `/id`). For more information about creating containers with hierarchical partition keys, see [Create a container by using hierarchical partition keys](hierarchical-partition-keys.md#create-a-container-by-using-hierarchical-partition-keys). |
| 220 | + |
| 221 | +To disable this feature set 'enableHierarchicalPartitionKeyIdLastLevel' property back to false. |
| 222 | + |
| 223 | +## Frequently asked questions |
| 224 | + |
| 225 | +### Why am I getting errors related to the 20-GB limit? |
| 226 | + |
| 227 | +This typically means a single logical partition (a single partition key value) has accumulated more than 20 GB of data. Switching to HPK and ensuring the final level is unique (for example, `/id`) helps prevent unbounded growth under one value. To proactively monitor for logical partitions approaching this limit, see [Create alerts to monitor logical partition key storage size](how-to-alert-on-logical-partition-key-storage-size.md). |
| 228 | + |
| 229 | +### Why does my request fail with "The last level of the hierarchical partition key must be '/id'"? |
| 230 | + |
| 231 | +With `EnforceHierarchicalPartitionKeyIdLastLevel` enabled, your items must include every partition key property in the hierarchy. For example, if your HPK is `/tenantId`, `/userId`, `/id`, then each item must have `tenantId`, `userId`, and `id` properties. The request must supply the matching full partition key value for point reads, updates, and deletes. If this is not needed please disable. |
| 232 | + |
| 233 | +### Why can't I create a container with a non-hierarchical partition key? Request failing with "Non-hierarchical partition key collection creation is blocked" |
| 234 | + |
| 235 | +After you enable `EnforceHierarchicalPartitionKeyIdLastLevel`, you must use hierarchical partition keys for all newly created containers. This restriction doesn't affect existing containers. If this is not needed please disable. |
| 236 | + |
| 237 | +### Can I change an existing container to use hierarchical partition keys? |
| 238 | + |
| 239 | +No. Partition key configuration is immutable. To adopt HPK (or to add a unique last level like `/id`), create a new container with the desired HPK definition and [migrate your data by using container copy jobs](container-copy.md). |
| 240 | + |
| 241 | +### Can I still use transactional batch, stored procedures, or triggers? |
| 242 | + |
| 243 | +If your usage depends on grouping multiple items under a single shared partition key value, a unique-last-level HPK (ending in `/id`) isn't compatible. If you need these features, consider an HPK design where the last level isn't unique (or use an alternative data model), and validate that it still avoids exceeding the 20-GB logical partition limit for your workload. |
| 244 | + |
| 245 | +## Next steps |
| 246 | + |
| 247 | +- [Hierarchical partition keys in Azure Cosmos DB](hierarchical-partition-keys.md) |
| 248 | +- [Frequently asked questions on hierarchical partition keys in Azure Cosmos DB](hierarchical-partition-keys-faq.yml) |
| 249 | +- [Partitioning and horizontal scaling in Azure Cosmos DB](partitioning.md) |
0 commit comments