Skip to content
Get Started for Free

Cosmos DB

Azure Cosmos DB is a globally distributed, multi-model NoSQL database service designed for high availability and low latency. It supports multiple APIs including SQL (NoSQL), MongoDB, Cassandra, Gremlin, and Table, enabling teams to choose the data model that best fits their application. Cosmos DB is commonly used for real-time applications, globally replicated datasets, and multi-tenant SaaS platforms that require predictable performance at any scale. For more information, see Introduction to Azure Cosmos DB.

LocalStack for Azure provides a local environment for building and testing applications that make use of Azure Cosmos DB. The supported APIs are available on our API Coverage section, which provides information on the extent of Cosmos DB’s integration with LocalStack.

This guide walks you through creating Cosmos DB accounts, databases, and containers using the SQL and MongoDB APIs.

Launch LocalStack using your preferred method. For more information, see Introduction to LocalStack for Azure. Once the container is running, enable Azure CLI interception by running:

Terminal window
lstk az start-interception

This command points the az CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API. To revert this configuration, run:

Terminal window
lstk az stop-interception

This reconfigures the az CLI to send commands to the official Azure management REST API.

This section walks through creating a Cosmos DB account with the SQL API, creating a database and a container, and listing resources.

Create a resource group to hold all resources created in this guide:

Terminal window
az group create --name rg-cosmos-demo --location eastus
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo",
"location": "eastus",
"name": "rg-cosmos-demo",
"properties": { "provisioningState": "Succeeded" },
"type": "Microsoft.Resources/resourceGroups"
}

Create a Cosmos DB account configured for the SQL API. Tags and capabilities are stored and returned, so tools that compare the response with their configuration, such as Terraform and Bicep, do not report drift:

Terminal window
az cosmosdb create \
--name mycosmosaccount \
--resource-group rg-cosmos-demo \
--locations regionName=eastus \
--tags env=dev
Output
{
"databaseAccountOfferType": "Standard",
"documentEndpoint": "https://mycosmosaccount.cosmos.documents.localhost.localstack.cloud:4511/",
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mycosmosaccount",
"instanceId": "7f34833d-901c-429f-ae09-da2e48417e21",
"kind": "GlobalDocumentDB",
"location": "East US",
"name": "mycosmosaccount",
"provisioningState": "Succeeded",
"resourceGroup": "rg-cosmos-demo",
"tags": {
"env": "dev"
},
"type": "Microsoft.DocumentDB/databaseAccounts",
...
}

The documentEndpoint points at the emulated account. Applications use it exactly as they would use the Azure endpoint; see Connect with an SDK for the certificate setup.

The account uses provisioned throughput, because later sections set throughput on its database. Azure does not allow that on a serverless account (--capabilities EnableServerless).

Running the same az cosmosdb create again updates the existing account in place: it keeps its instanceId, its keys and its databases, and only the properties you pass change. Real Azure rejects an account name that is already taken elsewhere, and so does LocalStack.

Change properties of an existing account with az cosmosdb update, which sends a PATCH request. Only the properties you pass change:

Terminal window
az cosmosdb update \
--name mycosmosaccount \
--resource-group rg-cosmos-demo \
--tags env=test \
--query "{name:name, tags:tags, instanceId:instanceId}"
Output
{
"instanceId": "7f34833d-901c-429f-ae09-da2e48417e21",
"name": "mycosmosaccount",
"tags": {
"env": "test"
}
}

Retrieve the primary and secondary access keys for the account:

Terminal window
az cosmosdb keys list \
--name mycosmosaccount \
--resource-group rg-cosmos-demo
Output
{
"primaryMasterKey": "C2y6yDjf5/R+ob0N8A7C...",
"primaryReadonlyMasterKey": "C2y6yDjf5/R+ob0N8A7C...",
"secondaryMasterKey": "C2y6yDjf5/R+ob0N8A7C...",
"secondaryReadonlyMasterKey": "C2y6yDjf5/R+ob0N8A7C..."
}

Retrieve the connection string for the account:

Terminal window
az cosmosdb keys list \
--type connection-strings \
--name mycosmosaccount \
--resource-group rg-cosmos-demo \
--query "connectionStrings[0].connectionString"
Output
"AccountEndpoint=https://mycosmosaccount.cosmos.documents.localhost.localstack.cloud:4511/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;"

Create a SQL API database within the Cosmos DB account, with dedicated throughput:

Terminal window
az cosmosdb sql database create \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo \
--name mydb \
--throughput 400
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mycosmosaccount/sqlDatabases/mydb",
"name": "mydb",
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases"
...
}

Create a SQL container with a partition key path of /id and a default time to live. The partition key, the indexing policy, the default TTL and unique key policies you pass are applied to the container and returned:

Terminal window
az cosmosdb sql container create \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo \
--database-name mydb \
--name mycontainer \
--partition-key-path /id \
--ttl 3600
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mycosmosaccount/sqlDatabases/mydb/containers/mycontainer",
"name": "mycontainer",
"resource": {
"defaultTtl": 3600,
"id": "mycontainer",
"partitionKey": {
"kind": "Hash",
"paths": [
"/id"
]
},
...
},
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
}

Running az cosmosdb sql database create or az cosmosdb sql container create again for an existing resource updates it in place, which is what a Bicep or Terraform re-deployment does. Mutable properties such as the TTL and the indexing policy are replaced; a changed partition key is rejected, as on Azure:

Terminal window
az cosmosdb sql container create \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo \
--database-name mydb \
--name mycontainer \
--partition-key-path /id \
--ttl 7200 \
--query "{name:name, defaultTtl:resource.defaultTtl}"
Output
{
"defaultTtl": 7200,
"name": "mycontainer"
}

Read and change the throughput of a database or container. A resource created without dedicated throughput has no throughput settings, and reading them returns NotFound, as on Azure:

Terminal window
az cosmosdb sql database throughput show \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo \
--name mydb
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mycosmosaccount/sqlDatabases/mydb/throughputSettings/default",
"resource": {
"instantMaximumThroughput": "10000",
"minimumThroughput": "400",
"softAllowedMaximumThroughput": "1000000",
"throughput": 400,
...
},
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/throughputSettings"
}
Terminal window
az cosmosdb sql database throughput update \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo \
--name mydb \
--throughput 1000 \
--query "resource.throughput"
Output
1000

The same commands exist for containers (az cosmosdb sql container throughput show|update) and for MongoDB databases and collections (az cosmosdb mongodb database|collection throughput show|update). Autoscale settings (--max-throughput) are stored and reported too. Throughput is recorded and returned, but request units are not metered or enforced.

List all SQL databases in the account and all containers within the database:

Terminal window
az cosmosdb sql database list \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo
Output
[
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mycosmosaccount/sqlDatabases/mydb",
"name": "mydb",
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases"
}
]

Then list all containers in the database:

Terminal window
az cosmosdb sql container list \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo \
--database-name mydb
Output
[
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mycosmosaccount/sqlDatabases/mydb/containers/mycontainer",
"name": "mycontainer",
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
}
]

Reading a resource that does not exist returns the same NotFound error as Azure, and deleting one that does not exist succeeds, so tools that read before they create, or retry a delete, behave as they do against Azure:

Terminal window
az cosmosdb sql container show \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo \
--database-name mydb \
--name missing
Output
ERROR: (NotFound) Message: {"code":"NotFound","message":"Message: {\"Errors\":[\"Resource Not Found. Learn more: https://aka.ms/cosmosdb-tsg-not-found\"]}..."}
Code: NotFound

The emulated account speaks the Cosmos DB REST protocol, so the official SDKs work against it unchanged. The endpoint uses a certificate issued by the LocalStack root CA. Download it from the running emulator and make it trusted by your SDK, for example through REQUESTS_CA_BUNDLE for the Python SDK or NODE_EXTRA_CA_CERTS for the Node.js SDK:

Terminal window
curl -s -o ls-root-ca.crt http://localhost:4566/_localstack/certs/ca/LocalStack_LOCAL_Root_CA.crt
export REQUESTS_CA_BUNDLE=$PWD/ls-root-ca.crt

Export the account endpoint and primary key for the SDK to read:

Terminal window
COSMOS_ENDPOINT=$(az cosmosdb show \
--name mycosmosaccount \
--resource-group rg-cosmos-demo \
--query "documentEndpoint" \
--output tsv)
COSMOS_KEY=$(az cosmosdb keys list \
--name mycosmosaccount \
--resource-group rg-cosmos-demo \
--query "primaryMasterKey" \
--output tsv)
export COSMOS_ENDPOINT COSMOS_KEY

Create a database, a container and an item with the Python SDK, reading the endpoint and key from those variables:

import os
from azure.cosmos import CosmosClient, PartitionKey
client = CosmosClient(os.environ["COSMOS_ENDPOINT"], os.environ["COSMOS_KEY"])
database = client.create_database_if_not_exists("appdb")
container = database.create_container_if_not_exists("orders", partition_key=PartitionKey(path="/customerId"))
container.upsert_item({"id": "order-1", "customerId": "c-42", "total": 19.99})

Resources created through the data plane are visible to the management plane, so an application can create its own databases and containers and az, Bicep or Terraform still see them:

Terminal window
az cosmosdb sql database list \
--account-name mycosmosaccount \
--resource-group rg-cosmos-demo \
--query "[].name"
Output
[
"mydb",
"appdb"
]

This section walks through creating a Cosmos DB account with the MongoDB API, creating a database, and connecting with a MongoDB client.

Create a second Cosmos DB account configured for the MongoDB API. The requested server version is stored and returned, but it does not change the version of the backing MongoDB server. Use a driver compatible with the backing server.

Terminal window
az cosmosdb create \
--name mymongoaccount \
--resource-group rg-cosmos-demo \
--locations regionName=eastus \
--kind MongoDB \
--server-version 7.0
Output
{
"apiProperties": {
"serverVersion": "7.0"
},
"capabilities": [
{
"name": "EnableMongo"
}
],
"databaseAccountOfferType": "Standard",
"documentEndpoint": "https://mymongoaccount.documents.azure.com:443/",
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mymongoaccount",
"kind": "MongoDB",
"location": "East US",
"name": "mymongoaccount",
"provisioningState": "Succeeded",
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts",
...
}

Retrieve the MongoDB-compatible connection string for the account:

Terminal window
az cosmosdb keys list \
--name mymongoaccount \
--resource-group rg-cosmos-demo \
--type connection-strings \
--query "connectionStrings[0].connectionString" \
--output tsv
Output
mongodb://primary:<key>@mymongoaccount.mongo.cosmos.localhost.localstack.cloud:4512/

The host name resolves to the emulator and the port is assigned per account, so use the connection string exactly as returned.

Create a MongoDB database within the account:

Terminal window
az cosmosdb mongodb database create \
--account-name mymongoaccount \
--resource-group rg-cosmos-demo \
--name mymongodb
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mymongoaccount/mongodbDatabases/mymongodb",
"name": "mymongodb",
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases"
...
}

Create a MongoDB collection inside the database with a shard key, a unique index and dedicated throughput. The shard key and the index options are applied to the collection and returned:

Terminal window
az cosmosdb mongodb collection create \
--account-name mymongoaccount \
--resource-group rg-cosmos-demo \
--database-name mymongodb \
--name mycollection \
--shard userId \
--idx '[{"key":{"keys":["_id"]}},{"key":{"keys":["userId"]},"options":{"unique":true}}]' \
--throughput 400
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mymongoaccount/mongodbDatabases/mymongodb/collections/mycollection",
"name": "mycollection",
"resource": {
"id": "mycollection",
"indexes": [
{
"key": {
"keys": [
"_id"
]
},
"options": null
},
{
"key": {
"keys": [
"userId"
]
},
"options": {
"expireAfterSeconds": null,
"unique": true
}
}
],
"shardKey": {
"userId": "Hash"
},
...
},
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections"
}

Collections that an application creates through the MongoDB driver are listed by az cosmosdb mongodb collection list as well.

Extract the connection string and connect to the MongoDB database using mongosh:

Terminal window
CONN_STR=$(az cosmosdb keys list \
--name mymongoaccount \
--resource-group rg-cosmos-demo \
--type connection-strings \
--query "connectionStrings[0].connectionString" \
--output tsv)
mongosh "$CONN_STR"

Delete the Cosmos DB account and confirm it no longer appears in the list:

Terminal window
az cosmosdb delete \
--name mycosmosaccount \
--resource-group rg-cosmos-demo \
--yes
az cosmosdb list --resource-group rg-cosmos-demo
Output
[
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-cosmos-demo/providers/Microsoft.DocumentDB/databaseAccounts/mymongoaccount",
"kind": "MongoDB",
"name": "mymongoaccount",
"provisioningState": "Succeeded",
"resourceGroup": "rg-cosmos-demo",
"type": "Microsoft.DocumentDB/databaseAccounts"
}
]

Delete the second Cosmos DB account configured for the MongoDB API:

Terminal window
az cosmosdb delete \
--name mymongoaccount \
--resource-group rg-cosmos-demo \
--yes

Then list all Cosmos DB accounts to confirm the resource group is now empty:

Terminal window
az cosmosdb list --resource-group rg-cosmos-demo
Output
[]
  • Account lifecycle: Create, read, update (PUT and PATCH), list, and delete Cosmos DB accounts for both SQL and MongoDB API kinds. Re-deploying an existing account updates it in place and keeps its keys and data.
  • Account properties: Tags, capabilities, the MongoDB server version, consistency policy, failover priorities and properties such as enableFreeTier, publicNetworkAccess and minimalTlsVersion are stored and returned.
  • Account key management: Retrieve primary and secondary master keys and read-only keys.
  • Connection strings: Retrieve connection strings for the API for NoSQL (SQL) and for MongoDB via az cosmosdb keys list --type connection-strings.
  • Name availability check: Validate account name uniqueness; a taken name cannot be claimed from another resource group or subscription.
  • SQL databases: Create, read, update, list, and delete SQL (NoSQL) databases within an account.
  • SQL containers: Create, read, update, list, and delete SQL containers with partition key (including hierarchical keys), indexing policy, default TTL, unique key policy and conflict resolution policy.
  • Throughput settings: Read and update manual or autoscale throughput of SQL databases and containers and of MongoDB databases and collections.
  • MongoDB databases: Create, read, list, and delete MongoDB databases within an account; re-deploying an existing database keeps it and its collections.
  • MongoDB collections: Create, read, update, list, and delete MongoDB collections with shard key, indexes (including unique and expireAfterSeconds options) and throughput settings.
  • Data plane integration: Databases, containers and collections created through the Cosmos DB SDKs or a MongoDB driver are visible to the management plane, and vice versa.
  • Native MongoDB access: Connect directly to the local MongoDB backend using a standard MongoDB client.
  • Cosmos DB for PostgreSQL: Create, start, stop, restart and delete clusters (Microsoft.DBforPostgreSQL/serverGroupsv2) with firewall rules, backed by a local PostgreSQL server.
  • Table API not supported: The Cosmos DB Table API is not emulated.
  • Cassandra API not supported: The Cosmos DB Cassandra API is not emulated.
  • Gremlin API not supported: The Cosmos DB Gremlin (graph) API is not emulated.
  • Cosmos DB for PostgreSQL: The backing server is a plain PostgreSQL instance without the Citus extension, so distributed tables are not available. Worker nodes exist as metadata only. Azure has retired this service for new clusters.
  • Global distribution not emulated: Multi-region replication and conflict resolution are accepted at the model level but not executed.
  • Change feed and triggers: Change feed processing and Cosmos DB triggers for Azure Functions are not emulated.
  • Throughput and RU metering: Throughput settings are stored and returned, but request unit (RU) consumption is not tracked or enforced. Migrating between manual and autoscale throughput is not supported. A serverless account (EnableServerless) accepts throughput settings, which Azure rejects.
  • RBAC for data plane: Cosmos DB SQL role definitions and role assignments are not implemented, and data plane requests are not authorized: any key or Microsoft Entra token is accepted, and disableLocalAuth is not enforced.
  • Key regeneration and failover: Regenerating account keys and changing failover priorities of an existing account are not supported.
  • Stored procedures, triggers and user-defined functions: Not supported through the management plane.

The following samples demonstrate how to use Azure Cosmos DB with LocalStack for Azure. Each comes in a Python and a .NET version:

  • Web App and Cosmos DB for NoSQL API (Python, .NET)
  • Web App and Cosmos DB for MongoDB API (Python, .NET)
  • AKS workload and Cosmos DB for NoSQL API (Python, .NET)
  • AKS workload and Cosmos DB for MongoDB API (Python, .NET)

50 of 310 operations implemented

Operation ▲Implemented ▼
Page 1 of 0
Was this page helpful?