Azure Cosmos DB + Functions Cookbook— static client
By definition, synergy happens when the interaction between two elements produces an effect greater than the individual elements’ contribution.
Azure Cosmos DB is Microsoft’s globally distributed multi-model database, when we team it up with Azure Functions, Azure’s serverless compute service, the result is the ideal database for the serverless era.
In this series of posts I’ll explore different recipes, gotchas and examples of this integration targeting specific scenarios and act as building blocks for your architecture.
Using and scaling
With Azure Functions, we can create small pieces of code that will run based on events (time, HTTP calls, message queues, database operations, to name a few) and can scale independently to adjust to your computational needs. While we technically do not see nor worry about the servers hosting our Functions (it’s serverless after all!), there is a Runtime (or ScriptHost) that maintains the memory space (besides other things) where our Functions run.
When working with Azure Cosmos DB, we might have seen code that uses the
using statement with the DocumentClient (after all, it implements the IDisposable interface) so we might be tempted to do this in our Function’s code:
The problem with this approach is that it is creating an instance of the DocumentClient in each execution. We all know the woes of this approach for the HttpClient (and if you don’t, please read it right after this article!), and it has the exact same effect here: If the Function is getting a high volume of triggers, we not only will be penalizing the performance of our database calls with the initialization overhead but the memory consumption will raise and we might even incur in socket exhaustion scenarios.
The static client
One of the first and easiest-to-achieve performance improvement we can implement when working with Azure Cosmos DB is to use a single DocumentClient instance for all the service calls (see the full performance article for more). When we are building applications, we could achieve this by Depedency Injection frameworks to maintain a Singleton instance, but how can we achieve this in our Functions’ code? Turns out it’s pretty easy! Just declare the DocumentClient as static outside of your Function’s Run code:
For security purposes, the code is reading the Cosmos DB Endpoint and Key from the Application Settings. Alternatively you could also use Azure Key Vault to store and retrieve this information. For more information, see my other related article.
This will effectively maintain one instance of the DocumentClient for all your Function’s executions within the same ScriptHost (instance) and improve the overall performance by reusing the same client for all service calls.
In an scenario where your Function App has multiple instances, each instance will maintain its own static client (it will not be shared among instances).
Stay tuned for more recipes!
Other posts in this series:
- Azure Cosmos DB + Functions Cookbook — HTTP querying
- Azure Cosmos DB + Functions Cookbook — output collector
- Azure Cosmos DB + Functions Cookbook — live migration
- Azure Cosmos DB + Functions Cookbook — search indexing
- Azure Cosmos DB + Functions Cookbook — secure client
- Azure Cosmos DB + Functions Cookbook — multi trigger
- Azure Cosmos DB + Functions Cookbook — Connection modes
- Azure Cosmos DB + Functions Cookbook — Multi master & preferred region
- Azure Cosmos DB + Functions Cookbook — Shared throughput and new health logs
- Azure Cosmos DB + Functions Cookbook — monitoring Trigger pending work