Skip to main content
Azure
  • 3 min read

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

We live in amazing times when people and businesses at 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 experience, and many more.

This post was co-authored by Mikhail Shilkov, Software Engineer, Pulumi.

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.

 

An image showing globally distributed applications.

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
  • Add a Traffic Manager to route user requests to the nearest application endpoint

A diagram showing the flow of global application with Azure and Pulumi.

Global application with Azure and Pulumi

 

However, instead of coding this manually, we can rely on Pulumi’s CosmosApp component as described in How To Build Globally Distributed Applications with Azure Cosmos DB and Pulumi. The component creates distributed Azure Cosmos DB resources, as well as the front-end routing component while allowing pluggable compute layer implementation.

You can find the sample code in Reusable Component to Create Globally-distributed Applications with Azure Cosmos DB.

Pulumi CLI executes the code, translate it to the tree of resources to create, and deploys all of them to Azure:

A screenshot showing Pulumi's CLI executing the code.

After the command succeeds, the application is up and running in three regions of my choice.

Next steps

Infrastructure as code is instrumental in enabling modern DevOps practices in the universe of global and scalable cloud applications.

Pulumi lets you use a general-purpose programming language to define infrastructure. It brings the best tools and practices from the software development world to the domain of infrastructure management.

Try the CosmosApp (available on GitHub—TypeScript, C#) with serverless functions, containers, or virtual machines to get started with Pulumi and Azure.