Session: How to Enable Optimistic Concurrency

By default, optimistic concurrency checks are turned off. Changes made outside our session object will be overwritten. Concurrent changes to the same document will use the Last Write Wins strategy.

You can enable the optimistic concurrency strategy either globally, at the document store level or a per session basis. In either case, with optimistic concurrency enabled, RavenDB will generate a concurrency exception (and abort all modifications in the current transaction) when the document has been modified on the server side after the client received and modified it. You can see the sample code below on the specific on

Note that useOptimisticConcurrency only applies to documents that has been modified by the session. Loading documents users/1-A and users/2-A in a session, modifying users/1-A and then calling saveChanges() will succeed, regardless of the optimistic concurrency setting, even if users/2-A has changed in the meantime. If the session were to try to save to users/2-A as well with optimistic concurrency turned on, then an exception will be raised and the updates to both users/1-A and users/2-A will be cancelled.

Another option is to control optimistic concurrency per specific document.
To enable it, you can supply a Change Vector to Store. If you don't supply a 'Change Vector' or if the 'Change Vector' is null, then optimistic concurrency will be disabled. Setting the 'Change Vector' to an empty string will cause RavenDB to ensure that this document is a new one and doesn't already exists.

Setting optimistic concurrency per specific document overrides the use of the useOptimisticConcurrency field from the advanced session operations.

Enabling for a specific Session

session.advanced.useOptimisticConcurrency = true;

const product = new Product();
product.name = "Some Name";

await session.store(product, "products/999");
await session.saveChanges();

{
    const anotherSession = store.openSession();
    const otherProduct = await anotherSession.load("products/999");
    otherProduct.name = "Other Name";

    await anotherSession.saveChanges();
}

product.name = "Better Name";
await session.saveChanges(); //  will throw ConcurrencyException error

Enabling Globally

The first example shows how to enable optimistic concurrency for a particular session. This can be also turned on globally, for all opened sessions by using the convention store.conventions.useOptimisticConcurrency.

store.conventions.useOptimisticConcurrency = true;

{
    const session = store.openSession();
    const isSessionUsingOptimisticConcurrency
        = session.advanced.useOptimisticConcurrency; // true
}

Turning Off Optimistic Concurrency for a Single Document when it is Enabled on Session

Optimistic concurrency can be turned off for a single document by passing null as a change vector value to store() method even when it is turned on for an entire session (or globally).

{
    const session = store.openSession();
    const product = new Product();
    product.name = "Some Name";

    await session.store(product, "products/999");
    await session.saveChanges();
}

{
    const session = store.openSession();
    session.advanced.useOptimisticConcurrency = true;

    const product = new Product();
    product.setName("Some Other Name");

    session.store(product, null, "products/999");
    session.saveChanges(); // will NOT throw Concurrency exception
}

Turning On Optimistic Concurrency for a New Document when it is Disabled on Session

Optimistic concurrency can be turned on for a new document by passing "" as a change vector value to store() method even when it is turned off for an entire session (or globally). It will cause to throw ConcurrencyException if the document already exists.

{
    const session = store.openSession();
    const product = new Product();
    product.name = "Some Name";
    await session.store(product, "products/999");
    await session.saveChanges();
}

{
    session.advanced.useOptimisticConcurrency = false; // default value

    const product = new Product();
    product.setName("Some Other Name");

    session.store(product, "", "products/999");
    session.saveChanges(); // will throw Concurrency exception
}