Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
4.0 : 10
3.2 : 9
3.1 : 9
3.0 : 9
2.0 : 8
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
4.0 : 10
3.2 : 9
3.1 : 9
3.0 : 9
2.0 : 8
Expand Down
2 changes: 2 additions & 0 deletions menu/menu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,8 @@
Articles:
- Url: persistence/upgrades/cosmosdb-1to2
Title: Version 1 to 2
- Url: persistence/upgrades/cosmosdb-3.1to3.2
Title: Version 3.1 to 3.2
- Title: DynamoDB
Articles:
- Url: persistence/upgrades/dynamodb-2to3
Expand Down
11 changes: 8 additions & 3 deletions persistence/cosmosdb/defaultcontainer.include.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
The default container can be set by using the following configuration API:
The container that is used by default for all incoming messages is specified via the `DefaultContainer(..)` configuration API:

snippet: CosmosDBDefaultContainer

The container that is used by default for all incoming messages is specified via `DefaultContainer(..)`. When installers are enabled, this (default) container will be created if it doesn't exist.
#if-version [3, )
**Added in version 3.2.0:** If the container information is being extracted during runtime from a message instance (header or message body), the default container specified will be overwritten by the last extractor in the pipeline. For example, if a [Header Extractor](/persistence/cosmosdb/transactions.md#specifying-the-container-to-use-for-the-transaction-using-message-header-values) (physical stage) and a [Message Extractor](/persistence/cosmosdb/transactions.md#specifying-the-container-to-use-for-the-transaction-using-the-message-contents) (logical stage) are both configured, then the container information within the Message Extractor would be used.

To opt out of creating the default container, either disable the installers or use:
> [!NOTE]
> **Added in version 3.2.0:** The exception to the above is if the extractor fails to pull container information from the message (logical), then the container information in the header (physical) will be used. If this also fails, the configured default container will be used as a fallback. If there is no default container configured, an exception will be thrown.
#end-if

When installers are enabled, this (default) container will be created if it doesn't exist. To opt-out of creating the default container, either disable the installers or use `DisableContainerCreation()`:

snippet: CosmosDBDisableContainerCreation

Expand Down
9 changes: 3 additions & 6 deletions persistence/cosmosdb/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ A `TokenCredential` can be provided by using the corresponding [`CosmosClient`](

### Customizing the database used

By default, the persister will store records in a database named `NServiceBus` and use a container per endpoint, using the endpoint name as the name of the container.

The database name can be customized using the following configuration API:
By default, the persister will store records in a database named `NServiceBus`. This can be overwritten by using the following configuration API:

snippet: CosmosDBDatabaseName

Expand Down Expand Up @@ -90,16 +88,15 @@ snippet: CosmosDBConfigureThrottlingWithBuilder

## Transactions

The Cosmos DB persister supports using the [Cosmos DB transactional batch API](https://devblogs.microsoft.com/cosmosdb/introducing-transactionalbatch-in-the-net-sdk/). However, Cosmos DB only allows operations to be batched if all operations are performed within the same logical partition key. This is due to the distributed nature of the Cosmos DB service, which does not support distributed transactions.
The Cosmos DB persister supports using the [Cosmos DB transactional batch API](https://devblogs.microsoft.com/cosmosdb/introducing-transactionalbatch-in-the-net-sdk/). However, Cosmos DB only allows operations to be batched if all operations are performed within the [same logical partition key](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/transactional-batch?tabs=dotnet). This is due to the distributed nature of the Cosmos DB service, which does not support distributed transactions.

The [transactions](transactions.md) documentation provides additional details on how to configure NServiceBus to resolve the incoming message to a specific partition key to take advantage of this Cosmos DB feature.

## Outbox

### Storage format

> [!WARNING]
> When the default partition key is not explicitly set, outbox rows are not separated by endpoint name. As a result, multiple logical endpoints cannot share the same database and container since [message identities are not unique across endpoints from a processing perspective](/nservicebus/outbox/#message-identity). To avoid conflicts, either separate different endpoints into different containers or [override the partition key](transactions.md).
partial: outboxstorageformat

### Outbox cleanup

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
> [!WARNING]
> _The below limitation has been resolved in `NServiceBus.Persistence.CosmosDB 3.2`. Its recommended that customers [update to 3.2](/persistence/upgrades/cosmosdb-3.1to3.2.md) if affected._
>
> For control messages, a default partition key in the format `{messageId}` will be used, however these Outbox records are not separated by endpoint name. As a result, multiple logical endpoints cannot share the same database and container since [message identities are not unique across endpoints from a processing perspective](/nservicebus/outbox/#message-identity). To avoid conflicts, either separate different endpoints into different containers, [override the partition key](transactions.md), or [update to NServiceBus.Persistence.CosmosDB 3.2](/persistence/upgrades/cosmosdb-3.1to3.2.md).
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#### Version 3.2.0 and over

A default [synthetic partition key](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/synthetic-partition-keys) will be used for all incoming messages, in the format `{endpointName}-{messageId}`, if not explicitly [overwritten](/persistence/cosmosdb/transactions.md#specifying-the-partitionkey-to-use-for-the-transaction) at runtime.

> [!NOTE]
> The [default partition key should be overwritten](/persistence/cosmosdb/transactions.md#specifying-the-partitionkey-to-use-for-the-transaction) whenever the message handler creates or updates business records in CosmosDB. To guarantee atomicity, explicitly set the Outbox partition key to match the partition key of your business record. This is a requirement for including both the business record and the Outbox record in the same [Cosmos DB transactional batch](https://learn.microsoft.com/en-us/azure/cosmos-db/partitioning-overview). Conversely, for simplicity, you can use the default partition key when a handler's logic does not involve persisting business data.

To support backward compatibility of control messages during migration, the persistence includes a fallback mechanism. When enabled (default), and if a record is not found using the synthetic key format, the system falls back to the legacy `{messageId}` format. Since the fallback mechanism involves an additional read operation on the Outbox container, it is recommended to turn it off once all legacy records have expired.

```csharp
endpointConfiguration
.EnableOutbox()
.DisableReadFallback();
```

> [!WARNING]
> Since [message identities are not unique across endpoints from a processing perspective](/nservicebus/outbox/#message-identity), when overwriting the default synthetic key, either separate different endpoints into different containers or [override the default synthetic partition key](transactions.md) in a way that ensures message identities are unique to each processing endpoint.

#### Version 3.1.0 and under

> [!WARNING]
> _The below limitation has been resolved in `NServiceBus.Persistence.CosmosDB 3.2.0`. Its recommended that customers [update to 3.2](/persistence/upgrades/cosmosdb-3.1to3.2.md) if affected._
>
> For control messages, a default partition key in the format `{messageId}` will be used, however these Outbox records are not separated by endpoint name. As a result, multiple logical endpoints cannot share the same database and container since [message identities are not unique across endpoints from a processing perspective](/nservicebus/outbox/#message-identity). To avoid conflicts, either separate different endpoints into different containers, [override the partition key](transactions.md), or [update to NServiceBus.Persistence.CosmosDB 3.2](/persistence/upgrades/cosmosdb-3.1to3.2.md).
2 changes: 0 additions & 2 deletions persistence/cosmosdb/transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ Additional overloads are available for extracting `PartitionKey`.

## Specifying the `Container` to use for the transaction

The Container to use can be specified by defining a default container:

include: defaultcontainer

Optionally, the `Container` to use can specified during message processing by providing the `Container` name and partition key path using the `ContainerInformation` object.
Expand Down
27 changes: 27 additions & 0 deletions persistence/upgrades/cosmosdb-3.1to3.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: Cosmos DB Persistence Upgrade from 3.1 to 3.2
summary: Instructions on how to upgrade NServiceBus.Persistence.CosmosDB 3.1 to 3.2
component: CosmosDB
reviewed: 2025-09-30
isUpgradeGuide: true
---

## Changes to Container Information Overrides

Customers that have both a [default container](/persistence/cosmosdb/#usage-customizing-the-container-used), and a [message container extractor](/persistence/cosmosdb/transactions.md#specifying-the-container-to-use-for-the-transaction-using-the-message-contents) configured will be affected by this update.

**In version 3.1 and under**, when a default container and a message container extractor are both configured, the container information is not overwritten by the message container extractor and falls back to the configured default container. The expected outcome is that the container information sourced from the message extractor overrides the default container configured.

**From version 3.2 and over**, the message container extractor correctly overrides the configured default container information.

### Impact

As a result of the above issue, customers may be unintentionally relying on the use of the default container over the configured message container extractor.

### Solution

Affected customers should perform one of the below options prior to updating to version 3.2:

1. Customers can remove the configured message container extractor and only rely on the default container.
2. Customers can update their message container extractor to use the same container specified as the default container.
3. Customers can [migrate relevant records](https://learn.microsoft.com/en-us/azure/cosmos-db/container-copy?tabs=online-copy&pivots=api-nosql) from the default container to the container specified in the message container extractor. This option may require [changing the container partition key](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/change-partition-key).