Manage Azure Cosmos DB for NoSQL resources with terraform
APPLIES TO: NoSQL
In this article, you learn how to use terraform to deploy and manage your Azure Cosmos DB accounts, databases, and containers.
This article shows terraform samples for NoSQL accounts.
Important
- Account names are limited to 44 characters, all lowercase.
- To change the throughput (RU/s) values, redeploy the terraform file with updated RU/s.
- When you add or remove locations to an Azure Cosmos account, you can't simultaneously modify other properties. These operations must be done separately.
- To provision throughput at the database level and share across all containers, apply the throughput values to the database options property.
To create any of the Azure Cosmos DB resources below, copy the example into a new terraform file (main.tf) or alternatively, have two separate files for resources (main.tf) and variables (variables.tf). Be sure to include the azurerm provider either in the main terraform file or split out to a separate providers file. All examples can be found on the terraform samples repository.
terraform {
required_version = ">= 1.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 3.0, < 4.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.0"
}
}
}
provider "azurerm" {
features {}
}
Azure Cosmos account with autoscale throughput
Create an Azure Cosmos account in two regions with options for consistency and failover, with database and container configured for autoscale throughput that has most index policy options enabled.
main.tf
resource "azurerm_resource_group" "example" {
name = "${random_pet.prefix.id}-rg"
location = var.location
}
resource "random_string" "db_account_name" {
count = var.cosmosdb_account_name == null ? 1 : 0
length = 20
upper = false
special = false
numeric = false
}
locals {
cosmosdb_account_name = try(random_string.db_account_name[0].result, var.cosmosdb_account_name)
}
resource "azurerm_cosmosdb_account" "example" {
name = local.cosmosdb_account_name
location = var.cosmosdb_account_location
resource_group_name = azurerm_resource_group.example.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
enable_automatic_failover = false
geo_location {
location = var.location
failover_priority = 0
}
consistency_policy {
consistency_level = "BoundedStaleness"
max_interval_in_seconds = 300
max_staleness_prefix = 100000
}
depends_on = [
azurerm_resource_group.example
]
}
resource "azurerm_cosmosdb_sql_database" "main" {
name = var.cosmosdb_sqldb_name
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
autoscale_settings {
max_throughput = var.max_throughput
}
}
resource "azurerm_cosmosdb_sql_container" "example" {
name = var.sql_container_name
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
database_name = azurerm_cosmosdb_sql_database.main.name
partition_key_path = "/definition/id"
partition_key_version = 1
autoscale_settings {
max_throughput = var.max_throughput
}
indexing_policy {
indexing_mode = "consistent"
included_path {
path = "/*"
}
included_path {
path = "/included/?"
}
excluded_path {
path = "/excluded/?"
}
}
unique_key {
paths = ["/definition/idlong", "/definition/idshort"]
}
}
resource "random_pet" "prefix" {
prefix = var.prefix
length = 1
}
variables.tf
variable "prefix" {
type = string
default = "cosmos-db-autoscale"
description = "Prefix of the resource name"
}
variable "location" {
type = string
default = "eastus"
description = "Resource group location"
}
variable "cosmosdb_account_name" {
type = string
default = null
description = "Cosmos db account name"
}
variable "cosmosdb_account_location" {
type = string
default = "eastus"
description = "Cosmos db account location"
}
variable "cosmosdb_sqldb_name" {
type = string
default = "default-cosmosdb-sqldb"
description = "value"
}
variable "sql_container_name" {
type = string
default = "default-sql-container"
description = "SQL API container name."
}
variable "max_throughput" {
type = number
default = 4000
description = "Cosmos db database max throughput"
validation {
condition = var.max_throughput >= 4000 && var.max_throughput <= 1000000
error_message = "Cosmos db autoscale max throughput should be equal to or greater than 4000 and less than or equal to 1000000."
}
validation {
condition = var.max_throughput % 100 == 0
error_message = "Cosmos db max throughput should be in increments of 100."
}
}
Azure Cosmos account with analytical store
Create an Azure Cosmos account in one region with a container with Analytical TTL enabled and options for manual or autoscale throughput.
main.tf
resource "azurerm_resource_group" "example" {
name = "${random_pet.random_prefix.id}-rg"
location = var.location
}
resource "random_string" "db_account_name" {
count = var.cosmosdb_account_name == null ? 1 : 0
length = 20
upper = false
special = false
numeric = false
}
locals {
cosmosdb_account_name = try(random_string.db_account_name[0].result, var.cosmosdb_account_name)
}
resource "azurerm_cosmosdb_account" "example" {
name = local.cosmosdb_account_name
location = var.cosmosdb_account_location
resource_group_name = azurerm_resource_group.example.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
enable_automatic_failover = false
analytical_storage_enabled = true
geo_location {
location = var.location
failover_priority = 0
}
consistency_policy {
consistency_level = "BoundedStaleness"
max_interval_in_seconds = 300
max_staleness_prefix = 100000
}
depends_on = [
azurerm_resource_group.example
]
}
resource "azurerm_cosmosdb_sql_database" "example" {
name = var.cosmosdb_sqldb_name
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
throughput = var.throughput
}
resource "azurerm_cosmosdb_sql_container" "main" {
name = var.sql_container_name
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
database_name = azurerm_cosmosdb_sql_database.example.name
partition_key_path = "/definition/id"
partition_key_version = 1
throughput = 400
analytical_storage_ttl = var.analytical_storage_ttl
indexing_policy {
indexing_mode = "consistent"
included_path {
path = "/*"
}
included_path {
path = "/included/?"
}
excluded_path {
path = "/excluded/?"
}
}
unique_key {
paths = ["/definition/idlong", "/definition/idshort"]
}
}
resource "random_pet" "random_prefix" {
prefix = var.name_prefix
}
variables.tf
variable "name_prefix" {
type = string
default = "101-cosmos-db-analyticalstore"
description = "Prefix for resource group name"
}
variable "location" {
type = string
default = "westus"
description = "Resource group location"
}
variable "cosmosdb_account_name" {
type = string
default = null
description = "Cosmos db account name"
}
variable "cosmosdb_account_location" {
type = string
default = "westus"
description = "Cosmos db account location"
}
variable "cosmosdb_sqldb_name" {
type = string
default = "default-sqldb-name"
description = "value"
}
variable "throughput" {
type = number
default = 400
description = "Cosmos db database throughput"
validation {
condition = var.throughput >= 400 && var.throughput <= 1000000
error_message = "Cosmos db manual throughput should be equal to or greater than 400 and less than or equal to 1000000."
}
validation {
condition = var.throughput % 100 == 0
error_message = "Cosmos db throughput should be in increments of 100."
}
}
variable "sql_container_name" {
type = string
default = "default-sql-container-name"
description = "SQL API container name."
}
variable "analytical_storage_ttl" {
type = number
default = -1
description = "Analytical Storage TTL in seconds."
}
Azure Cosmos account with standard provisioned throughput
Create an Azure Cosmos account in two regions with options for consistency and failover, with database and container configured for standard throughput that has most policy options enabled.
main.tf
resource "azurerm_resource_group" "example" {
name = "${random_pet.prefix.id}-rg"
location = var.location
}
resource "azurerm_cosmosdb_account" "example" {
name = "${random_pet.prefix.id}-cosmosdb"
location = var.cosmosdb_account_location
resource_group_name = azurerm_resource_group.example.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
enable_automatic_failover = false
geo_location {
location = var.location
failover_priority = 0
}
consistency_policy {
consistency_level = "BoundedStaleness"
max_interval_in_seconds = 300
max_staleness_prefix = 100000
}
depends_on = [
azurerm_resource_group.example
]
}
resource "azurerm_cosmosdb_sql_database" "main" {
name = "${random_pet.prefix.id}-sqldb"
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
throughput = var.throughput
}
resource "azurerm_cosmosdb_sql_container" "example" {
name = "${random_pet.prefix.id}-sql-container"
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
database_name = azurerm_cosmosdb_sql_database.main.name
partition_key_path = "/definition/id"
partition_key_version = 1
throughput = var.throughput
indexing_policy {
indexing_mode = "consistent"
included_path {
path = "/*"
}
included_path {
path = "/included/?"
}
excluded_path {
path = "/excluded/?"
}
}
unique_key {
paths = ["/definition/idlong", "/definition/idshort"]
}
}
resource "random_pet" "prefix" {
prefix = var.prefix
length = 1
}
variables.tf
variable "prefix" {
type = string
default = "cosmosdb-manualscale"
description = "Prefix of the resource name"
}
variable "location" {
type = string
default = "eastus"
description = "Resource group location"
}
variable "cosmosdb_account_location" {
type = string
default = "eastus"
description = "Cosmos db account location"
}
variable "throughput" {
type = number
default = 400
description = "Cosmos db database throughput"
validation {
condition = var.throughput >= 400 && var.throughput <= 1000000
error_message = "Cosmos db manual throughput should be equal to or greater than 400 and less than or equal to 1000000."
}
validation {
condition = var.throughput % 100 == 0
error_message = "Cosmos db throughput should be in increments of 100."
}
}
Azure Cosmos DB container with server-side functionality
Create an Azure Cosmos account, database and container with a stored procedure, trigger, and user-defined function.
main.tf
resource "azurerm_resource_group" "example" {
name = "${random_pet.prefix.id}-rg"
location = var.location
}
resource "azurerm_cosmosdb_account" "example" {
name = "${random_pet.prefix.id}-cosmosdb"
location = var.cosmosdb_account_location
resource_group_name = azurerm_resource_group.example.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
enable_automatic_failover = false
geo_location {
location = var.location
failover_priority = 0
}
consistency_policy {
consistency_level = "BoundedStaleness"
max_interval_in_seconds = 300
max_staleness_prefix = 100000
}
depends_on = [
azurerm_resource_group.example
]
}
resource "azurerm_cosmosdb_sql_database" "main" {
name = "${random_pet.prefix.id}-sqldb"
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
throughput = var.throughput
}
resource "azurerm_cosmosdb_sql_container" "example" {
name = "${random_pet.prefix.id}-sql-container"
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
database_name = azurerm_cosmosdb_sql_database.main.name
partition_key_path = "/definition/id"
partition_key_version = 1
throughput = 400
indexing_policy {
indexing_mode = "consistent"
included_path {
path = "/*"
}
included_path {
path = "/included/?"
}
excluded_path {
path = "/excluded/?"
}
}
unique_key {
paths = ["/definition/idlong", "/definition/idshort"]
}
}
resource "azurerm_cosmosdb_sql_stored_procedure" "example" {
name = "${random_pet.prefix.id}-sql-stored-procedure"
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
database_name = azurerm_cosmosdb_sql_database.main.name
container_name = azurerm_cosmosdb_sql_container.example.name
body = "function () { var context = getContext(); var response = context.getResponse(); response.setBody('Hello, World'); }"
}
resource "azurerm_cosmosdb_sql_trigger" "example" {
name = "${random_pet.prefix.id}-sql-trigger"
container_id = azurerm_cosmosdb_sql_container.example.id
body = "function validateToDoItemTimestamp(){var context=getContext();var request=context.getRequest();var itemToCreate=request.getBody();if(!('timestamp'in itemToCreate)){var ts=new Date();itemToCreate['timestamp']=ts.getTime();}request.setBody(itemToCreate);}"
operation = "Create"
type = "Pre"
}
resource "azurerm_cosmosdb_sql_function" "example" {
name = "${random_pet.prefix.id}-sql-function"
container_id = azurerm_cosmosdb_sql_container.example.id
body = "function tax(income){if(income==undefined)throw'no input';if(income<1000)return income*0.1;else if(income<10000)return income*0.2;else return income*0.4;}"
}
resource "random_pet" "prefix" {
prefix = var.prefix
length = 1
}
variables.tf
variable "prefix" {
type = string
default = "cosmos-db-ss-func"
description = "Prefix of the resource name"
}
variable "location" {
type = string
default = "eastus"
description = "Resource group location"
}
variable "cosmosdb_account_location" {
type = string
default = "eastus"
description = "Cosmos db account location"
}
variable "throughput" {
type = number
default = 400
description = "Cosmos db database throughput"
validation {
condition = var.throughput >= 400 && var.throughput <= 1000000
error_message = "Cosmos db manual throughput should be equal to or greater than 400 and less than or equal to 1000000."
}
validation {
condition = var.throughput % 100 == 0
error_message = "Cosmos db throughput should be in increments of 100."
}
}
Azure Cosmos DB account with Microsoft Entra ID and role-based access control
Create an Azure Cosmos account, a natively maintained Role Definition, and a natively maintained Role Assignment for a Microsoft Entra identity.
main.tf
data "azurerm_client_config" "current" {}
locals {
current_user_object_id = coalesce(var.msi_id, data.azurerm_client_config.current.object_id)
}
resource "azurerm_resource_group" "example" {
name = "${random_pet.prefix.id}-rg"
location = var.location
}
resource "random_string" "db_account_name" {
count = var.cosmosdb_account_name == null ? 1 : 0
length = 20
upper = false
special = false
numeric = false
}
locals {
cosmosdb_account_name = try(random_string.db_account_name[0].result, var.cosmosdb_account_name)
}
resource "azurerm_cosmosdb_account" "example" {
name = local.cosmosdb_account_name
location = var.cosmosdb_account_location
resource_group_name = azurerm_resource_group.example.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
enable_automatic_failover = false
geo_location {
location = var.location
failover_priority = 0
}
consistency_policy {
consistency_level = "BoundedStaleness"
max_interval_in_seconds = 300
max_staleness_prefix = 100000
}
depends_on = [
azurerm_resource_group.example
]
}
resource "azurerm_cosmosdb_sql_database" "example" {
name = var.cosmosdb_sqldb_name
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
throughput = var.throughput
}
resource "azurerm_cosmosdb_sql_container" "example" {
name = var.sql_container_name
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
database_name = azurerm_cosmosdb_sql_database.example.name
partition_key_path = "/definition/id"
partition_key_version = 1
throughput = 400
indexing_policy {
indexing_mode = "consistent"
included_path {
path = "/*"
}
included_path {
path = "/included/?"
}
excluded_path {
path = "/excluded/?"
}
}
unique_key {
paths = ["/definition/idlong", "/definition/idshort"]
}
}
resource "azurerm_cosmosdb_sql_role_definition" "example" {
name = "examplesqlroledef"
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
type = "CustomRole"
assignable_scopes = [
"/subscriptions/${data.azurerm_client_config.current.subscription_id}/resourceGroups/${azurerm_resource_group.example.name}/providers/Microsoft.DocumentDB/databaseAccounts/${azurerm_cosmosdb_account.example.name}"
]
permissions {
data_actions = ["Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read"]
}
}
resource "azurerm_cosmosdb_sql_role_assignment" "example" {
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
role_definition_id = azurerm_cosmosdb_sql_role_definition.example.id
principal_id = local.current_user_object_id
scope = "/subscriptions/${data.azurerm_client_config.current.subscription_id}/resourceGroups/${azurerm_resource_group.example.name}/providers/Microsoft.DocumentDB/databaseAccounts/${azurerm_cosmosdb_account.example.name}"
}
resource "random_pet" "prefix" {
prefix = var.name_prefix
}
variables.tf
variable "name_prefix" {
type = string
default = "101-cosmos-db-aad-rbac"
description = "Prefix for resource group name"
}
variable "location" {
type = string
default = "westus"
description = "Resource group location"
}
variable "cosmosdb_account_name" {
type = string
default = null
description = "Cosmos db account name"
}
variable "cosmosdb_account_location" {
type = string
default = "westus"
description = "Cosmos db account location"
}
variable "cosmosdb_sqldb_name" {
type = string
default = "default-sqldb-name"
description = "value"
}
variable "msi_id" {
type = string
default = null
description = "If you're executing the test with user assigned identity, please pass the identity principal id to this variable."
}
variable "throughput" {
type = number
default = 400
description = "Cosmos db database throughput"
validation {
condition = var.throughput >= 400 && var.throughput <= 1000000
error_message = "Cosmos db manual throughput should be equal to or greater than 400 and less than or equal to 1000000."
}
validation {
condition = var.throughput % 100 == 0
error_message = "Cosmos db throughput should be in increments of 100."
}
}
variable "sql_container_name" {
type = string
default = "default-sql-container-name"
description = "SQL API container name."
}
Free tier Azure Cosmos DB account
Create a free-tier Azure Cosmos account and a database with shared throughput that can be shared with up to 25 containers.
main.tf
resource "azurerm_resource_group" "example" {
name = "${random_pet.prefix.id}-rg"
location = var.location
}
resource "azurerm_cosmosdb_account" "example" {
name = random_pet.prefix.id
location = var.cosmosdb_account_location
resource_group_name = azurerm_resource_group.example.name
offer_type = "Standard"
kind = "GlobalDocumentDB"
enable_automatic_failover = false
enable_free_tier = true
geo_location {
location = var.location
failover_priority = 0
}
consistency_policy {
consistency_level = "BoundedStaleness"
max_interval_in_seconds = 300
max_staleness_prefix = 100000
}
depends_on = [
azurerm_resource_group.example
]
}
resource "azurerm_cosmosdb_sql_database" "main" {
name = "${random_pet.prefix.id}-cosmosdb-sqldb"
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
throughput = var.throughput
}
resource "azurerm_cosmosdb_sql_container" "example" {
name = "${random_pet.prefix.id}-sql-container"
resource_group_name = azurerm_resource_group.example.name
account_name = azurerm_cosmosdb_account.example.name
database_name = azurerm_cosmosdb_sql_database.main.name
partition_key_path = "/definition/id"
partition_key_version = 1
throughput = var.throughput
indexing_policy {
indexing_mode = "consistent"
included_path {
path = "/*"
}
included_path {
path = "/included/?"
}
excluded_path {
path = "/excluded/?"
}
}
unique_key {
paths = ["/definition/idlong", "/definition/idshort"]
}
}
resource "random_pet" "prefix" {
prefix = var.prefix
length = 1
}
variables.tf
variable "prefix" {
type = string
default = "cosmos-db-free-tier"
description = "Prefix of the resource name"
}
variable "location" {
type = string
default = "eastus"
description = "Resource group location"
}
variable "cosmosdb_account_location" {
type = string
default = "eastus"
description = "Cosmos db account location"
}
variable "throughput" {
type = number
default = 400
description = "Cosmos db database throughput"
validation {
condition = var.throughput >= 400 && var.throughput <= 1000000
error_message = "Cosmos db manual throughput should be equal to or greater than 400 and less than or equal to 1000000."
}
validation {
condition = var.throughput % 100 == 0
error_message = "Cosmos db throughput should be in increments of 100."
}
}
Next steps
Here are some more resources: