Edit

Multitenancy and Azure Cosmos DB

This article describes partitioning strategies, isolation models, and Azure Cosmos DB features for multitenant solutions.

Multitenancy requirements

When you plan a multitenant solution, you must meet two key requirements:

  • Ensure security and performance isolation between tenants. As the provider, you must meet security requirements and ensure that each tenant meets performance requirements.

  • Maintain a low cost for each tenant. As the provider, you must ensure that the cost to run the application remains sustainable as it scales.

These two requirements often conflict and require you to prioritize one over the other. The guidance in this article helps you understand these trade-offs and make informed decisions when you design your multitenant solution.

Partitioning strategies

Azure Cosmos DB for NoSQL automatically partitions the items in a container based on an application-defined partition key. Items that have the same full partition-key value form a logical partition. Azure Cosmos DB manages how logical partitions map to physical partitions as the container's storage and throughput requirements grow. A full logical partition can store up to 20 GB of data and consume up to 10,000 request units per second (RU/s).

Choose a partition key

Choosing a partition key is an important design-time decision because it affects data and request distribution, query efficiency, and transaction boundaries. Choose a property with a wide range of values and access patterns that distribute storage and request volume evenly. An uneven distribution can create a hot partition, which receives a disproportionate share of requests and becomes a bottleneck while other partitions have unused capacity. Hot partitions can cause rate limiting even when the container has unused throughput.

In a multitenant container, a tenant identifier can be an effective partition key when each tenant's data and request load fit within one logical partition and most operations are scoped to one tenant. For larger or unevenly active tenants, consider hierarchical partition keys, synthetic partition keys, or a high-cardinality key such as /id, depending on the workload's query and write patterns. For tenant-specific decision guidance, see Partition-key-per-tenant model and Hierarchical partition keys.

Plan resource and throughput boundaries

An Azure Cosmos DB account contains databases, and each database has one or more containers. A container is the unit of scalability for storage and throughput. You can provision throughput directly on a container or at the database level for the containers in that database to share. Throughput that's provisioned on a container is reserved for that container, but the logical partitions and tenants within it share that throughput. Shared database throughput doesn't guarantee a specific amount of throughput for each container.

Containers can scale to unlimited aggregate storage and throughput, subject to account quotas. As a container grows, Azure Cosmos DB adds and manages physical partitions. Before you introduce application-managed sharding across containers or accounts, evaluate whether a hierarchical or synthetic partition key can meet the workload's scale and query requirements.

Account-level configuration applies to the databases and containers in the account. This configuration includes regions, consistency, networking, and access control. If a tenant requires independent account-level configuration or a stronger security and performance boundary, use a separate account. For more information, see Database-account-per-tenant model, Databases, containers, and items, and Provisioned throughput.

Plan item, query, and transaction boundaries

Within a container, the combination of an item's full partition-key value and its id uniquely identifies the item. The same id value can appear in different logical partitions. Include both values in point reads so that Azure Cosmos DB can route the operation directly to the logical partition.

Queries are scoped to a container, not to a logical partition. A query can target one logical partition, a hierarchical partition-key prefix, or multiple logical partitions within the container. Cross-partition queries are supported, but fan-out queries can consume more RUs and increase latency. If data is distributed across multiple containers or accounts, the application must query those resources separately and combine the results. Design partition keys so that common queries target the smallest practical set of logical partitions.

Every operation on a single item is transactional. Azure Cosmos DB provides ACID guarantees with snapshot isolation, so a failed operation is rolled back and concurrent readers don't observe partial changes. Multi-item transactions and transactional batches are limited to items that have the same full partition-key value in a container. With hierarchical partition keys, transactional operations require the complete partition-key path. For more information, see Transactions and optimistic concurrency control.

Use server-side programming within a logical partition

You can register stored procedures, triggers, and user-defined functions (UDFs) on a container. Stored procedures and triggers can perform transactional operations only on items that have the same full partition-key value. If the JavaScript code throws an exception, Azure Cosmos DB rolls back the transaction.

Use stored procedures or triggers to maintain integrity across related items only when those items share the full partition key. Triggers don't run automatically. The application must specify them when it submits the associated operation. UDFs extend query expressions, but they don't provide a transactional write boundary.

For many transactional write scenarios, you can also use transactional batch operations from the client SDK. For more information about server-side programming, see Stored procedures, triggers, and UDFs.

Partitioning distributes data and throughput within a container, but it doesn't provide tenant-specific security or guaranteed performance isolation. For tenant-isolation options, see Isolation models.

Isolation models

Determine the level of isolation that you need between your tenants. For most solutions, we recommend that you use one of the following strategies, depending on your workload:

  • Business-to-consumer (B2C) software as a service (SaaS) solutions typically use a partition key for each tenant. One example of this type of solution is a conversational chatbot application that stores user chat history in Azure Cosmos DB.

  • Business-to-business (B2B) SaaS solutions typically use a database account for each tenant. One example of this type of solution is a content management system (CMS) that enterprises buy to publish digital content.

To choose the most appropriate isolation model, consider your business model and the tenants' requirements. For example, in B2C models, a business sells a product or service directly to an individual customer. Strong security and performance isolation for each individual customer typically isn't required. For the highest cost efficiency, these applications can store data for all tenants in the same container, and partition keys provide logical isolation.

However, in B2B models, providers sell different SKUs that correspond to different performance levels, service-level agreement (SLA) guarantees, or isolation requirements. Providers might give their customers control over the encryption keys that protect their data by using customer-managed keys, including cross-tenant customer-managed keys. For these applications, use a separate database account for each tenant so that you can tune and guarantee performance for each customer. Customer-managed keys are available only at the Azure Cosmos DB database-account level.

Partition-key-per-tenant model

In a partition-key-per-tenant model, the same Azure Cosmos DB container stores all data for your tenants by using a partition key like /TenantId. The tenants share the container's throughput.

Note

A request unit (RU) is a logical abstraction of the cost of a database operation or query. Typically, you provision a defined number of request units per second (RU/s) for your workload, which is called throughput.

Benefits

  • Simplified management: You place all tenants in one container that the tenant ID partitions. This approach creates only one billable resource that provisions and shares RU/s among multiple tenants. This model is easier to manage because only one RU/s setting affects cost for the entire multitenant workload.

Trade-offs and considerations

  • Resource contention: Shared throughput (RU/s) across tenants in the same container can cause contention during peak usage. This contention can create noisy neighbor problems and performance challenges if your tenants have high or overlapping workloads. Use this isolation model for workloads that don't need guaranteed RU/s on a single tenant and can share throughput.

  • Limited isolation: This approach provides logical isolation, not physical isolation. Use this isolation model for workloads that don't need guaranteed performance for each tenant or customer-managed keys for each tenant.

  • Less flexibility: If you isolate tenants by partition key, you can't customize account-level features like geo-replication, point-in-time restore, and customer-managed keys for each tenant.

  • Tenant recovery: Point-in-time restore operates at account and container boundaries, not at tenant partition-key values. To recover one tenant from a shared container, restore the container to a separate account and copy only the tenant's items back to the production container.

Azure Cosmos DB provides several features that help you optimize performance and manage costs for multitenant solutions. These features address common challenges like noisy neighbor problems and help you store data efficiently and query across tenants.

Hierarchical partition keys

For read-heavy workloads in which you typically query by tenant, we recommend using hierarchical partition keys to achieve the following benefits:

  • Scale beyond the full logical-partition limit: Set /TenantId as your first-level key and a high-cardinality field like /id as your second-level key so that each tenant can scale beyond the 20-GB storage and 10,000-RU/s limits of a full logical partition. You might have another hierarchy in your workload. For example, if you store data for each user in each tenant, set /TenantId as the first-level key, /UserId as the second-level key, and /id as the third-level key so that each user can scale beyond those limits.

    Note

    Features in Azure Cosmos DB, like stored procedures and atomic batch transactions, are only available at the full logical partition-key level. If you use hierarchical partition keys and partition by /id as your last-level key, you can't run stored procedures or do an atomic batch transaction at partial levels.

    For example, if you partition by /TenantId, /UserId, and /id, you can't run a stored procedure or do an atomic batch transaction by specifying only the /TenantId or only the /TenantId and /UserId. If you need to use these features, don't set /id as your last-level key.

  • Efficient queries: Queries that specify /TenantId or both /TenantId and /UserId are efficiently routed only to the subset of physical partitions that contains the relevant data, which avoids a full fan-out query. If the container has 1,000 physical partitions, but a specific /TenantId value is only on 5 physical partitions, the query is routed to the smaller number of relevant physical partitions.

Use hierarchical partition keys when you have high cardinality of values and uniform distribution of request volumes for your first-level keys. In a multitenant setting, you should have many tenants, ideally in the order of hundreds to thousands of tenants or more, and your tenants should have a similar usage pattern.

A hot partition and possible degraded performance might occur in the following scenarios:

  • You work with few tenants.

  • You work with a skewed workload in which a single tenant consistently consumes exponentially more RU/s than your other tenants, even when you use hierarchical partition keys.

Don't use hierarchical partition keys for workloads in which you don't have high cardinality for each tenant or when you need to optimize for write performance. In these scenarios, we recommend using synthetic partition keys or partitioning only by /id. These approaches let you spread writes evenly across all physical partitions.

You can construct a synthetic key in a way that optimizes for some queries. For example, a TenantId_UserId synthetic key slightly reduces the even distribution of data across all partitions, but it lets you efficiently query for a specific user in a tenant when you specify the full partition key. Query optimization is the main advantage of using a synthetic key instead of /id.

However, if your workload optimizes for write throughput, queries might not be relevant. You can partition by only /id to simplify your workload.

If you work with a few large tenants that consistently need higher request volumes than other tenants, consider isolating those tenants into their own database accounts. Keep the remaining tenants in a shared container.

Database-account-per-tenant model

In the database-account-per-tenant model, each tenant's data is stored in its own Azure Cosmos DB database account. Within each account, multiple containers can store data for different workloads or microservices. You can provision dedicated throughput on individual containers or share throughput among containers at the database level.

Benefits

  • High isolation: This approach avoids contention or noisy neighbor problems between tenants because each tenant's data is in its own dedicated Azure Cosmos DB account. Within the account, use dedicated container throughput when individual workloads require guaranteed RU/s.

  • Custom SLAs: Each tenant has its own account, so you can provide specific tailored resources, customer-facing SLAs, and guarantees because you can tune the resources in each tenant's database account independently to meet its performance needs.

  • Enhanced security: This approach allows customer-managed keys at the database-account level, so the provider can offer customer-managed keys for each tenant. If customer-managed keys are required, you must use database-account-per-tenant isolation.

  • Flexibility: You can turn on account-level features like geo-replication, point-in-time restore, and customer-managed keys at a per-tenant (database account) level as needed.

  • Tenant recovery: Account and container restore boundaries align with one tenant, which simplifies per-tenant recovery compared with selectively recovering a tenant from a shared container.

Trade-offs and considerations

  • More accounts to manage: This approach can be more complex because you have multiple Azure Cosmos DB accounts that each represent a tenant or customer. However, you can use Azure Cosmos DB fleets to simplify account management by sharing throughput (RU/s) across multiple database accounts. You can also use fleet analytics to monitor your usage at scale.

  • Cross-tenant query limitations: All tenants are in different accounts, so applications that query multiple tenants require multiple calls within the application's logic. Typically, these cross-tenant queries aren't part of the core transactional workload that provides the service to each tenant. Instead, they're part of an analytical workload that helps the provider understand broader trends and usage across different tenants or customers. For these use cases, use mirroring in Microsoft Fabric.

Fleet management and account configuration

Workload need Partition-key-per-tenant model Database-account-per-tenant model
Cost efficiency Optimize one container RU/s for the workload. Optimize cost by sharing RU/s within a fleet pool.
New tenant creation latency Immediate Immediate, if you create empty database accounts that have just-in-time (JIT) assignments to new tenants
Tenant data deletion Use application-managed deletion. If the tenant identifier is the full logical partition key, delete items by partition key (preview) can delete that logical partition. The feature can't delete by a partial hierarchical partition-key prefix. Delete the database account when the tenant leaves.
Data access security isolation You need to implement isolation within the application. RBAC
Geo-replication Per-tenant geo-replication isn't possible. Each database account can have custom regions configured.
Noisy neighbor prevention No Yes
Encryption key Same for all tenants Customer-managed key for each tenant
Throughput requirements More than 0 RUs per tenant More than 100 RUs per tenant
Queries across tenants The container acts as a boundary for queries. Use mirroring in Fabric for analytical queries.
Example use case B2C apps Premium or enterprise offer for B2B apps

We recommend the partition-key-per-tenant and database-account-per-tenant isolation models for most multitenant scenarios. Isolation by container or database is possible, but these approaches typically have trade-offs that the recommended isolation models address more effectively.

Container-per-tenant model

You can provision dedicated containers that each have their own RU/s for each tenant and place them in an Azure Cosmos DB database account. Each database account can only contain a limited number of containers, so you might need multiple accounts to hold data for all tenants. You need to keep track of which database account contains data for each customer, which adds complexity to your application.

Azure Cosmos DB also limits the throughput for metadata operations and number of databases or containers for each account. Metadata operations include reading the list of databases or containers in an account and reading and updating container settings. Because of these limits, we don't recommend this model. If a single account has several tenants, the volume of metadata operations increases and might not scale effectively. This model might also require you to manage multiple accounts to balance many tenants, which increases the complexity of your multitenant solution.

You can use the container-per-tenant model to achieve performance isolation for each tenant by setting up dedicated RU/s at the container level. You can also enhance security by using Azure RBAC. But the container-per-tenant model doesn't support tenant-specific customer-managed keys, because they're only set at the database-account level.

If you have many containers in a database account and you need to use Azure Cosmos DB data plane RBAC to assign a role to each container, you might encounter limits on the number of role assignments per account.

If you need performance isolation or customer-managed keys, consider using the database-account-per-tenant model and fleet pools to optimize cost for each tenant. If you don't need these features, consider using the partition-key-per-tenant model.

Database-per-tenant model

You can provision databases for each tenant and place them in the same database account. Like the container-per-tenant model, you might need multiple database accounts to hold data for all tenants and custom application logic to keep track of which database account a tenant belongs to.

You can use the database-per-tenant model to achieve performance isolation for each tenant by setting up shared RU/s at the database level or dedicated RU/s for each container. You can also enhance security by using Azure RBAC. But the database-per-tenant model doesn't support tenant-specific customer-managed keys because keys are set at the database-account level. We also don't typically recommend shared RU/s at the database level for high-traffic workloads because the performance for each container in the database isn't guaranteed.

If you need performance isolation or customer-managed keys, consider using the database-account-per-tenant model and fleet pools to optimize cost for each tenant. If you don't need these features, consider using the partition-key-per-tenant model.

Like the container-per-tenant model, we don't recommend this model because of the Azure Cosmos DB limits on throughput for metadata operations and number of databases or containers for each account.

Azure Cosmos DB features that support multitenancy

Use the following Azure Cosmos DB features in your multitenant solution.

Fleet pools

Fleet pools are primarily useful with the database-account-per-tenant model. For information about fleetspaces, pool configuration, tenant grouping, and throughput sharing, see Fleet management and account configuration.

Fleet analytics (preview)

Use fleet analytics, a feature of Azure Cosmos DB fleets, to analyze long-term trends in the database accounts in your fleet. Fleet analytics delivers performance, usage, and cost data as open-source Apache Delta Lake tables in Azure Data Lake Storage and Microsoft OneLake at an hourly cadence.

Use this data to track trends like which accounts are most active, how resources scale over time, which database accounts or tenants have the highest cost, and the most recent rotation of access keys. You can also use the data to write custom queries or build Power BI dashboards to analyze your fleet.

RU management

The Azure Cosmos DB pricing model is based on the number of RU/s that you provision or consume. Azure Cosmos DB provides several options to provision throughput. In a multitenant environment, your selection affects the performance and price of your Azure Cosmos DB resources.

For tenants that require guaranteed performance and security isolation, we recommend that you isolate tenants by database account, allocate dedicated RU/s to the tenant, and use fleet pools to handle extra capacity needs. For tenants that have less-stringent requirements, we recommend that you isolate tenants by partition key. Use this model to share RU/s among your tenants and optimize the cost for each tenant.

Azure Cosmos DB also provides a serverless tier, which suits workloads that have intermittent or unpredictable traffic.

Note

When you plan your Azure Cosmos DB configuration, consider the service quotas and limits.

To monitor and manage the costs associated with each tenant, remember that every operation that uses the Azure Cosmos DB API includes the RUs consumed. You can use this information to aggregate and compare the actual RUs that each tenant consumes. You can then identify tenants that have different performance characteristics. If a few tenants have significantly higher performance or isolation requirements, consider isolating them into their own account, with dedicated container RU/s. You can use a container partitioned by tenant ID to store data for the remaining tenants.

Resource governance features

Explore features that can help control the noisy neighbor problem when you use a partition key to isolate tenants.

Feature Description
Burst capacity Take advantage of the container's unused capacity in the last five minutes to cover future spikes.
Priority-based execution Specify high or low priority at a per-request level. When throughput contention occurs at the container level, high-priority requests are prioritized. Use this feature when multiple workloads have different performance requirements, such as a batch job versus an API that serves real-time user requests.
Throughput buckets (preview) Assign a specific percentage of RU/s that a set of requests can consume. For example, specify that requests from a batch job can only consume up to 10% of the container's total RU/s, but a critical user-facing API can consume up to 100% of the container's total RU/s.
Throughput redistribution (preview) Use this API to assign more RU/s to hot physical partitions.

For more information, see the following resources:

Customer-managed keys

Some tenants might need to use their own encryption keys. Azure Cosmos DB provides a customer-managed key feature. You apply this feature only at the level of an Azure Cosmos DB account. If tenants require their own encryption keys, you must use dedicated Azure Cosmos DB accounts to deploy the tenants.

For more information, see Set up customer-managed keys for your Azure Cosmos DB account by using Azure Key Vault.

Contributors

Microsoft maintains this article. The following contributors wrote this article.

Principal authors:

Other contributors:

  • Mark Brown | Principal PM Manager, Azure Cosmos DB
  • Vic Perdana | Cloud Solution Architect, Azure ISV
  • Theo van Kraay | Senior Program Manager, Azure Cosmos DB
  • Arsen Vladimirskiy | Principal Customer Engineer, FastTrack for Azure
  • Thomas Weiss | Principal Program Manager

To see nonpublic LinkedIn profiles, sign in to LinkedIn.

Next steps

To learn more about multitenancy and Azure Cosmos DB, watch the following videos:

  • Design scalable data layers for multitenant apps with Azure Cosmos DB: A session at Build 2025 that walks you through how to design for multitenancy on Azure Cosmos DB. Learn best practices from a real-world independent software vendor.

  • Multitenant applications with Azure Cosmos DB: A session at Build 2019 that covers performance isolation, cost management, consistency, latency, availability trade-offs, and security patterns for multitenant applications.

  • Build a multitenant SaaS on Azure Cosmos DB and Azure: A real-world case study about how Whally, a multitenant SaaS startup, builds a modern platform from scratch on Azure Cosmos DB and Azure. Whally makes design and implementation decisions that relate to partitioning, data modeling, secure multitenancy, performance, and real-time streaming from change feed to SignalR. All these solutions use ASP.NET Core on Azure App Service.

To review other Azure Cosmos DB architectural scenarios, see the following articles: