How to build globally distributed applications with Azure Cosmos DB and Pulumi

Rimma Nehme Product Manager and Architect, Azure Cosmos DB

Pulumi is reinventing how people build modern cloud applications, with a unique platform that combines deep systems and infrastructure innovation with elegant programming models and developer tools.

We live in amazing times when people and businesses on different continents can interact at the speed of light. Numerous industries and applications target users around the globe: e-commerce websites, multiplayer online games, connected IoT devices, collaborative work and leisure experiences, and many more. All of these applications demand computing and data infrastructure in proximity to the end-customers to minimize latency and keep the user experience engaging. The modern cloud makes these scenarios possible. 

Azure infrastructure

Azure Cosmos DB provides a turn-key data distribution to any number of regions, meaning that locations can be added or removed along the way while running production workloads. Azure takes care of data replication, resiliency, and efficiency while providing APIs for read and write operations with a latency of less than 10 milliseconds.

In contrast, compute services—virtual machines, container instances, Azure App Services, Azure Functions, and managed Azure Kubernetes Service—are located in a single Azure region. To make good use of the geographic redundancy of the database, users should deploy their application to each of the target regions.

Globally distributed application

Application regions must stay in sync with Azure Cosmos DB regions to enjoy low-latency benefits. Operational teams must manage the pool of applications and services to provide the correct locality in addition to auto-scaling configuration, efficient networking, security, and maintainability.

To help manage the complexity, the approach of infrastructure as code comes to the rescue.

Infrastructure as code

While the Azure portal is an excellent pane-of-glass for all Azure services, it shouldn’t be used directly to provision production applications. Instead, we should strive to describe the infrastructure in terms of a program which can be executed to create all the required cloud resources.

Traditionally, this could be achieved with an automation script, e.g., a PowerShell Cmdlet or a bash script calling the Azure CLI. However, this approach is laborious and error prone. Bringing an environment from its current state to the desired is often non-trivial. A failure in the middle of the script often requires manual intervention to repair environments, leading to downtime.

Desired state configuration is another style of infrastructure definition. A user describes the desired final state of infrastructure in a declarative manner, and the tooling takes care of bringing an environment from its current state to the parity with the desired state. Such a program is more natural to evolve and track changes.

Azure Resource Manager Templates is the bespoke desired-state-configuration tool in the world of Azure. The state is described as a JSON template, listing all the resources and properties. However, large JSON templates can be quite hard to write manually. They have a high learning curve and quickly become large, complex, verbose, and repetitive. Developers find themselves missing simple programming language possibilities like iterations or custom functions.

Pulumi solves this problem by using general-purpose programming languages to describe the desired state of cloud infrastructure. Using JavaScript, TypeScript, or Python reduces the amount of code many-fold, while bringing constructs like functions and components to the DevOps toolbox.

Global applications with Pulumi

To illustrate the point, we developed a TypeScript program to provision a distributed application in Azure. The target scenario requires quite a few resources to distribute the application across multiple Azure regions, including:

  • Provision an Azure Cosmos DB account in multiple regions

  • Deploy a copy of the application layer to each of those regions

  • Connect each application to the Azure Cosmos DB local replica