Back to Blog
3 min read

Azure Cosmos DB Serverless: Pay-Per-Request Pricing

Azure Cosmos DB serverless offers consumption-based pricing—pay only for the request units consumed and storage used. Perfect for intermittent workloads.

Serverless vs Provisioned

AspectServerlessProvisioned
PricingPer requestPer hour
ScalingAutomaticManual/Auto
Best forSporadic trafficSteady traffic
Max RU/s5,000Unlimited

Create Serverless Account

# Create serverless Cosmos DB account
az cosmosdb create \
    --name mycosmosdb \
    --resource-group myRG \
    --capabilities EnableServerless \
    --default-consistency-level Session \
    --locations regionName=eastus

Create Database and Container

using Microsoft.Azure.Cosmos;

// Connect to serverless account
var client = new CosmosClient(connectionString);

// Create database
var database = await client.CreateDatabaseIfNotExistsAsync("ecommerce");

// Create container (no throughput specification for serverless)
var container = await database.Database.CreateContainerIfNotExistsAsync(
    new ContainerProperties
    {
        Id = "orders",
        PartitionKeyPath = "/customerId"
    }
);

CRUD Operations

// Create item
var order = new Order
{
    Id = Guid.NewGuid().ToString(),
    CustomerId = "customer-123",
    Items = new[] { new OrderItem { ProductId = "prod-1", Quantity = 2 } },
    Total = 99.99m,
    CreatedAt = DateTime.UtcNow
};

var response = await container.CreateItemAsync(order, new PartitionKey(order.CustomerId));
Console.WriteLine($"Request charge: {response.RequestCharge} RUs");

// Read item
var readResponse = await container.ReadItemAsync<Order>(
    order.Id,
    new PartitionKey(order.CustomerId)
);
Console.WriteLine($"Read cost: {readResponse.RequestCharge} RUs");

// Query items
var query = new QueryDefinition("SELECT * FROM c WHERE c.customerId = @customerId")
    .WithParameter("@customerId", "customer-123");

var iterator = container.GetItemQueryIterator<Order>(query);
double totalRUs = 0;

while (iterator.HasMoreResults)
{
    var batch = await iterator.ReadNextAsync();
    totalRUs += batch.RequestCharge;
    foreach (var item in batch)
    {
        Console.WriteLine($"Order: {item.Id}");
    }
}
Console.WriteLine($"Query cost: {totalRUs} RUs");

Optimize Request Units

// Use point reads instead of queries when possible
// Point read: ~1 RU for 1KB document
var item = await container.ReadItemAsync<Order>(id, partitionKey);

// Query: 2.3+ RUs minimum
var query = container.GetItemQueryIterator<Order>(
    "SELECT * FROM c WHERE c.id = 'order-123'"
);

// Index only what you query
var containerProperties = new ContainerProperties
{
    Id = "orders",
    PartitionKeyPath = "/customerId",
    IndexingPolicy = new IndexingPolicy
    {
        IndexingMode = IndexingMode.Consistent,
        IncludedPaths = { new IncludedPath { Path = "/status/*" } },
        ExcludedPaths = { new ExcludedPath { Path = "/*" } }
    }
};

Batch Operations

// Transactional batch (same partition key)
var batch = container.CreateTransactionalBatch(new PartitionKey("customer-123"));

batch.CreateItem(order1);
batch.CreateItem(order2);
batch.UpsertItem(order3);

var batchResponse = await batch.ExecuteAsync();
Console.WriteLine($"Batch cost: {batchResponse.RequestCharge} RUs");

When to Use Serverless

  • Development and testing environments
  • Applications with variable/unpredictable traffic
  • New projects validating usage patterns
  • Workloads with idle periods
  • Low-throughput scenarios (<5,000 RU/s)

Cost Example

Scenario: 1 million requests/month, 10GB storage

Serverless:
- Requests: 1M × $0.25/million = $0.25
- Storage: 10GB × $0.25/GB = $2.50
- Total: ~$2.75/month

Provisioned (400 RU/s):
- Throughput: 400 × $0.008/hour × 730 = ~$23.36
- Storage: 10GB × $0.25/GB = $2.50
- Total: ~$25.86/month

Cosmos DB Serverless: scale-to-zero for your NoSQL workloads.

Michael John Peña

Michael John Peña

Senior Data Engineer based in Sydney. Writing about data, cloud, and technology.