Skip to content

If you’re considering using Cosmos Database (DB) SQL API for your next project, one of the fundamental design decisions you will face is how to partition your data.

In this post, we’ll take a look at some of the factors that may influence your partitioning strategy, and explore some examples of various partitioning strategies and compare their pros and cons.

Considerations

It is important that we know our data before deciding on our partition strategy to avoid issues further down the road. For example, consider the following:

Partition limits

There are limits to how much you can store in a logical and physical partition. At the time of writing, Azure Cosmos DB supports up to 20GB for a logical partition and 50GB for a physical partition.

When a physical partition is approaching its limit, Cosmos DB will split new physical partitions under the hood without affecting availability. When a logical partition limit is hit, Cosmos DB will throw the error message “Partition key reached maximum size of 20 GB” and we can no longer insert records into it.

Therefore, be mindful of how your data grows with respect to the partition key you choose.

Read uses-cases

In general, you would want to have an even distribution of partition key for write operations to avoid hot partitions. It is also important that you design data for your read operations because inefficient queries eat up “ ” significantly.

Identify what type of queries you need, e.g.

SDK limitations

There are various SDKs available to integrate with Cosmos DB. For the complete list, refer to the official documentation from Microsoft.

Your options depend on which Cosmos DB API you use (e.g. SQL API, Cassandra API, etc.) and which language your application code is written in. Not all SDKs are implemented the same and they have different feature limitations.

Cross-partition queries

While working with Node.js SDK , we found out that pagination is not supported for cross-partition queries. This had caused us to redesign the container’s partitioning strategy to fit our need for pagination while not having to migrate our application from Node.js to .NET platform.

Multi-tenancy systems

In the setting of a multi-tenancy system, all customers’ data goes into a single Cosmos DB container. There might be some active customers that generate high requests rates to the container, known as busy tenants. If the data is not segregated into different partitions by customer, others will be affected by the busy tenants. Requests have a much higher chance of getting throttled.

Note that the provisioned Request Units are split evenly between underlying physical partitions. E.g. You provisioned 1000 RU/s for a container, which at the moment has 5 physical partitions. Therefore, each physical partition supports the rate of 200 RU/s.

It is not in our control how partition keys are being distributed into different physical partitions and we might still have busy tenants affecting others.

Data retention

Physical partitions has a limit of storing 50GB of data. When data grows over time, there will be more physical partitions created under the hood. This also means that the throughput (RU/s) will be split among more physical partitions. As a result, you will need to provision more throughput (higher cost) to maintain the same request rate.

Data retention policy is something you would want to consider to keep the data growth in check. Cosmos DB has a Time to Live (TTL)  feature that let us specify how long we want to retain an item for. The items are deleted automatically by Cosmos DB using left-over Request Units.

If your data grows into sheer size and is meant to be stored indefinitely, consider moving less accessed data to a cheaper alternative storage.

Some example of partitioning strategies

In this section we’ll look at several examples of partioning strategies. By no means is this an exhaustive list though.

Random

The partition key is either composed wholly or partly of a random value, for example a randomly-generated guid.

Pros

Cons

Per tenant

If you have a multi-tenant system this means using the unique tenant identifier for the partition key.

Pros

Cons

Per tenant + category

This is somewhat similar to the ‘Per tenant’ scheme discussed above, but with additional identifiers for the category of data being stored.

An example might be {tenantid}_workflow to store all workflow-related documents for the tenant.

Pros

Cons

Per tenant + entity

This an extension of the previous scheme, but adds a unique identifier for the parent entity. This is suited for hierarchical data, where an entity has a collection of child entities.

For example, if we have a Workflow entity that contains multiple “WorkflowInstance” entities, we could use a partition scheme like this for the workflow instance documents: {tenantid}_workflowinstances_{parentworkflowid}

Pros

Cons

Per tenant + date period

This where each partition corresponds to a time period (a ‘bucket’) for a tenant. Say we wanted separate buckets for each month, we could use the scheme {tenantid}_{yyyyMM}.

This is suited for time-series event data where the document contains a fixed date property that determines what bucket the document goes into.

Pros

Cons

Next

In Part 2 we’ll take a deeper look at the ‘Per tenant + date period’ partitioning strategy and discover ways of managing pagination as we query across bucket boundaries.

 

 

Interested in exploring more engineering posts from our team here at Nintex? Click here to discover more.