# MongoDB Persistence Uses the [MongoDB document database](https://www.mongodb.com/) for storage. > [!NOTE] > NServiceBus.Storage.MongoDB supports MongoDB server versions 3.6 and higher ## Persistence at a glance For a description of each feature, see the [persistence at a glance legend](/persistence/index.md#persistence-at-a-glance). |Feature | | |:--- |--- |Supported storage types |Sagas, Outbox, Subscriptions |Transactions |Enabled and required by default |Concurrency control |Pessimistic concurrency only |Scripted deployment |Not supported |Installers |None. Documents are created in database at runtime as needed. ## Usage Add a NuGet package reference to `NServiceBus.Storage.MongoDB`. Configure the endpoint to use the persistence through the following configuration API: ```cs endpointConfiguration.UsePersistence(); ``` ### Customizing the connection By default, a `MongoClient` is created that connects to `mongodb://localhost:27017` and uses the endpoint name as its database name. Customize the server, port, and authentication database using the following configuration API: ```cs var persistence = endpointConfiguration.UsePersistence(); persistence.MongoClient(new MongoClient("SharedMongoUrl")); ``` Specify the database to use for NServiceBus documents using the following configuration API: ```cs var persistence = endpointConfiguration.UsePersistence(); persistence.DatabaseName("DatabaseName"); ``` ## Transactions MongoDB [transactions](https://docs.mongodb.com/manual/core/transactions/) are enabled and required by default. This allows the persister to use pessimistic locking and to update multiple saga instances and commit them atomically during message processing. > [!WARNING] > MongoDB transactions require a replica set or sharded cluster. Refer to the [MongoDB transaction documentation](https://docs.mongodb.com/manual/core/transactions/#transactions-and-atomicity) for more information about supported configurations and required MongoDB server versions. > [!NOTE] > The MongoDB persister supports transactions on shared clusters starting from version 2.1. ### Disabling transactions The following configuration API is available for compatibility with MongoDB server configurations that don't support transactions: ```cs var persistence = endpointConfiguration.UsePersistence(); persistence.UseTransactions(false); ``` Note that this disables the ability to use pessimistic locking for sagas, which might result in higher contention in the database. ### Shared transactions NServiceBus supports sharing MongoDB sessions between Saga persistence, Outbox storage, and business data. The shared session can be used to persist multiple document updates atomically. To use the shared transaction in a message handler: ```cs public Task Handle(MyMessage message, IMessageHandlerContext context) { var session = context.SynchronizedStorageSession.GetClientSession(); var collection = session.Client.GetDatabase("mydatabase").GetCollection("mycollection"); return collection.InsertOneAsync(session, new MyBusinessObject(), null, context.CancellationToken); } ``` > [!WARNING] > In order to participate in the shared transaction the MongoDB session must be passed into collection API calls as demonstrated above. The shared session can also be accessed via dependency injection using the `IMongoSynchronizedStorageSession` interface: ```cs class MyService { IMongoSynchronizedStorageSession sharedSession; // Resolved from DI container public MyService(IMongoSynchronizedStorageSession sharedSession) { this.sharedSession = sharedSession; } public Task Create() { return sharedSession.MongoSession.Client .GetDatabase("mydatabase") .GetCollection("mycollection") .InsertOneAsync(sharedSession.MongoSession, new MyBusinessObject()); } } ``` > [!WARNING] > In order to participate in the shared transaction, the MongoDB session must be passed into collection API calls as demonstrated above. > [!NOTE] > The `IMongoSynchronizedStorageSession` lifetime is scoped to the message processing pipeline. Do not resolve the shared session into dependencies with a _Singleton_ lifetime. #### Testing The `TestableMongoSynchronizedStorageSession` class in the `NServiceBus.Testing` namespace has been provided to facilitate [testing a handler](/nservicebus/testing/index.md) that utilizes the shared transaction feature. ## Outbox ## Storage format Outbox record documents are stored in a collection called `outboxrecord`. > [!WARNING] > Outbox documents are not separated by endpoint name. Because of that, multiple logical endpoints cannot share the same database since [message identities are not unique across endpoints from a processing perspective](/nservicebus/outbox/index.md#message-identity). ### Outbox cleanup When the outbox is enabled, the deduplication data is kept for seven days by default. To customize this time frame, use the following API: ```cs var persistence = endpointConfiguration.UsePersistence(); persistence.TimeToKeepOutboxDeduplicationData(TimeSpan.FromDays(30)); ``` ## Saga concurrency When simultaneously handling messages, conflicts may occur. See below for examples of the exceptions which are thrown. _[Saga concurrency](/nservicebus/sagas/concurrency.md)_ explains how these conflicts are handled and contains guidance for high-load scenarios. ### Starting a saga Example exception: ```text MongoDB.Driver.MongoCommandException: Command insert failed: WriteConflict. ``` ### Updating or deleting saga data Starting from version 2.2, MongoDB persistence uses [exclusive locks](https://docs.mongodb.com/manual/faq/concurrency/) when updating or deleting saga data. The saga persister tries to acquire an exclusive lock on the saga data for up to 60 seconds. If, within this time period, an exclusive lock cannot be acquired, a `TimeoutException` is thrown and regular message retry policies are applied. Example exception: ```text System.TimeoutException: Unable to acquire exclusive write lock for saga on collection 'collectionName' ``` In versions before version 2.2, MongoDB persistence uses [optimistic concurrency control](https://en.wikipedia.org/wiki/Optimistic_concurrency_control) when updating or deleting saga data. Example exception: ```text MongoDB.Driver.MongoCommandException: Command update failed: WriteConflict. ``` > [!NOTE] > This means that the relevant `Handle` method on the saga will be invoked, even though the message might be later rolled back. Hence it is important to ensure not to perform any work in saga handlers that can't roll back together with the message. This also means that should there be high levels of concurrency there will be N-1 rollbacks where N is the number of concurrent messages. This can cause throughput issues and might require design changes. ## Installer Installers are not supported. Indexes are created regardless of the installer settings.