From the trenches with Whally: Building an awesome multitenant SaaS with Azure Cosmos DB and Azure

Azure Cosmos DB · 3K views · 2021 · 58:26

Open on YouTube

Databases & storageSoftware architecture & designCloud, DevOps & reliabilitytalkdated

Why Stack Overflow recommends it

Stack Overflow users link it (often the speaker himself, Noah Stahl) when answering Cosmos DB questions about multitenancy via partitioning, diagnosing bursty RU throttling, and handling change feed load.

Recommended by 3 people across 2 different months, 2021 to 2021.

What it is

A case study session from the Azure Cosmos DB conference in which Noah Stahl walks through how his startup Whally built a multitenant SaaS platform on Azure Cosmos DB and ASP.NET Core on App Services. It covers partitioning, data modeling, secure multitenancy, performance, and streaming from the change feed to SignalR.

What people said

Strong rec Mark Brown · 2021-05 · Stack Overflow · on “Single cosmosclient per account”

Cosmos client instance is per account. You cannot create a single instance and have it connect to multiple accounts simultaneously. Generally speaking, multi-tenant apps in the same application instance are designed to be tenant per container or tenant per partition key. Applications which use the Cosmos account as the tenant boundary are often only done when tenants have different replication regions or have other networking or other needs, such as security which can only be managed at the account level. If this is not the case then I suggest you evaluate what your tenant boundary is. Tenant per account is an expensive option on a per tenant basis. It also has the highest operational overhe

Recommends Paul0515 · 2021-05 · Stack Overflow · on “CosmosDB RequestUnit Consumption Mismatch”

In order to make it clear this issue is fixed, I put the snippets from the comments here to clarify the solution: @noahstahl added this comment: Given the big difference between your expected throughput and throttling witnessed, it seems like you have some operations that are more expensive than you think, or more bursty. I'd try implementing more granular logging in the application code, e.g in this example [this video] The 'bursty' comment was the pointer to the solution. The avg numbers per minute are all OK, so there seems to be a big gap in expected usage vs required capacity provisioning. However if you look per second (by using the logs), it becomes clear that some seconds do not have any

Recommends Noah Stahl · 2021-05 · Stack Overflow · on “Database user permission vs where parameter”

This is a bit vague, can you provide more context on your goal? If you're asking about implementing multitenancy, I discuss one approach using partitioning in this talk: [this video]

Recommends Noah Stahl · 2021-05 · Stack Overflow · on “CosmosDB RequestUnit Consumption Mismatch”

Given the big difference between your expected throughput and throttling witnessed, it seems like you have some operations that are more expensive than you think, or more bursty. I'd try implementing more granular logging in the application code, e.g in this example [this video]

Recommends Noah Stahl · 2021-07 · Stack Overflow · on “CosmosDb slow changefeed performance with high partition key cardinality”

I wonder what you'd see if you architected the change feed consumption as a just a fast process to get changed items into a Service Bus queue, then some asynchronous queue consumers could fan out as needed to handle the queued burst. I describe this kind of approach in a recent project here: [this video]

Cites Noah Stahl · 2021-06 · Stack Overflow · on “Protecting endpoints using Session cookie ASP.NET Core”

I did this on recent project by implementing my own session storage in Cosmos DB via ITicketStore [LINK] (not with AddSession ). You configure the CookieAuthenticationOptions to persist authentication tickets through your custom store. Here's the gist, which allows using either cookies or JWT depending on whether request comes from browser or API client. The service configuration bits: // Authenticate using shared cookie for browser clients, and JWT tokens for API clients services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, cookieOptions) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtOptions); /