How to handle multiple cosmos db accounts with a single cosmosclient. Questions on multi tenancy

61 Views Asked by At

We have a multi-tenant B2B SaaS application and we're exploring the usage of Cosmos DB core SQL API. Our plans are to implement per cosmos account, single database with 499 containers. We choose a container per tenant approach something like the following:

|-- CosmosDB Account 1
|   |-- Database A
|       |-- Container Tenant 1
|       |-- Container Tenant 2
|       |-- ...
|       |-- Container Tenant 499
|
|-- CosmosDB Account 2
|   |-- Database B
|       |-- Container Tenant 500
|       |-- Container Tenant 501
|       |-- ...
|       |-- Container Tenant 998

This will keep growing up to about 500,000 container limit in a single Azure subscription based on the documentation on resource limits: limits

When the limit is reached a new azure subscription will be created and the same design will take place as our tenants grow. A master database will also exist, in order to keep track of tenants on our side. Master database will contain documents in regards to each tenant, which azure subscription, account/database they belong to. We plan to use an asp.net web api, it will be a monolith and shared across all tenants. The web api will be responsible for reads/writes for each tenant, across cosmos accounts for each tenants container.

We'll be using the .NET SDK for Azure Cosmos DB for the core SQL API. My question is what is the recommended approach on how to handle the client instance for the cosmos SDK? I found some information which talks about Best practices for multi-tenant applications for the cosmos SDK. Which states the following:

Applications that distribute usage across multiple tenants where each tenant is represented by a different database, container, or partition key within the same Azure Cosmos DB account should use a single client instance. A single client instance can interact with all the databases, containers, and partition keys within an account, and it's best practice to use the singleton pattern.

However, when each tenant is represented by a different Azure Cosmos DB account, it's required to create a separate client instance per account. The singleton pattern still applies for each client (one client for each account for the lifetime of the application), but if the volume of tenants is high, the number of clients can be difficult to manage. Connections can increase beyond the limits of the compute environment and cause connectivity issues.

So based on the recommendations with my design as context, does that mean I should have multiple CosmosClient instances, one for each cosmos account? If this is the case as we scale, lets take the scenario where we have 500,000 tenants, this would mean 1000 cosmos accounts which would translate to 1000 CosmosClient instances on a single asp.net web api? I'm having trouble understanding the implications of such a design, is this even feasible? Is it possible to just use a single CosmosClient instances for all accounts? I did find the following on stackoverflow, however is this approach recommended: Dependency Injection & connection strings / Multiple instances of a singleton which a user posted:

In the end, is this case, the best solution was the approach that was suggested by Mr. T. https://devblogs.microsoft.com/cosmosdb/httpclientfactory-cosmos-db-net-sdk/

I'm now still using one CosmosClient, Scoped. Which allows dynamic use of endpoints.

By injecting the IHttpClientFactory and setting the CosmosClientOptions like this;

{ HttpClientFactory = () => _httpClientFactory.CreateClient("cosmos") }); we are now making full use of the HttpClient and its ability to reuse ports.

It's be great to get some code examples and general guidance.

1

There are 1 best solutions below

2
Matias Quaranta On

My question is simply how to handle the cosmosclient when multiple cosmos accounts come into play and if its possible and or recommended to use a single cosmosclient.

The CosmosClient object is tied to an endpoint and an authentication method for that endpoint (a key or an identity or a resource token). The endpoint represents an account.

The endpoint cannot be changed, nor any of the Data Plane operations (such as CreateItemAsync) allow you to change it.

Having an HttpClientFactory with a shared HttpClient across CosmosClient instances is possible, however, if these instances talk to different accounts, they are not really sharing any connections and there is really no benefit of the shared HttpClient from the "reducing connections" point of view. Also, a shared HttpClient would only impact Gateway mode interactions.

The document you linked already has the answer to your question: "However, when each tenant is represented by a different Azure Cosmos DB account, it's required to create a separate client instance per account."