AI agents: use the documentation index at llms.txt to locate machine-readable pages. This section is indexed by https://docs.particular.net/persistence/llms.txt. The markdown version of this page is served as plain text. An MCP server at /mcp serves the same content via the search_docs and read_doc tools; it is read-only and needs no credentials. Markdown versions of documentation pages are available by appending .md to the page URL. Directory URLs use index.md. They are served as text/plain because some retrieval backends reject text/markdown.

How document versioning works

MongoDB provides no out-of-the-box concurrency control. A common pattern for supporting concurrency is using a document version number (int) that is used as a filter for update statements:

UpdateDefinition<BsonDocument> updateDefinition = updateBuilder.Inc(versionFieldName, 1);
FilterDefinition<BsonDocument> filterDefinition = Builders<BsonDocument>.Filter.Eq("_id", documentId)
    & Builders<BsonDocument>.Filter.Eq(versionFieldName, currentVersion);

//Define other update operations on the document

var modifiedDocument = await collection.FindOneAndUpdateAsync(
    filter: filterDefinition,
    update: updateDefinition,
    options: new FindOneAndUpdateOptions<BsonDocument, BsonDocument> { IsUpsert = false, ReturnDocument = ReturnDocument.After });

if (modifiedDocument == null)
{
    //The document was not updated because the version was already incremented.
}

By updating the document with a filter specifying the expected current version of the document, no update will be made if another process has incremented the version before the current process can. This ensures only one process/thread can update the saga at a time.

This pattern requires an element in the BsonDocument to store the current version value. Instead of requiring the user to provide this as a property of their saga data type, this package uses the MongoDB client's BSON serializer to add a version element to the serialized saga data as it is initially created and stored in the collection. When the serialized BsonDocument is later fetched, the version element's current value is retrieved before deserializing it to the saga data type. The current value is then retained for the lifetime of the saga message processing and is used to create the update filter.

By default, the BsonDocument element is named _version but it is possible to override the name of the version element for compatibility when migrating from previous community MongoDB persistences like NServiceBus.MongoDB or NServiceBus.Persistence.MongoDB.

Related Articles