I'm using MongoDB with the .NET driver and trying to implement an optimistic concurrency pattern with versioning using UpdateOneAsync and IsUpsert = true.

Here is my code:

public Task UpsertAsync(User user, CancellationToken cancellationToken) =>
    context.Users.UpdateOneAsync(
        Builders<User>.Filter.Eq(u => u.Id, user.Id) &
        Builders<User>.Filter.Lt(u => u.Version, user.Version),
        Builders<User>.Update
            .SetOnInsert(u => u.Id, user.Id)
            .Set(u => u.IsDeleted, user.IsDeleted)
            .Set(u => u.Version, user.Version)
            .Set(u => u.Name, user.Name)
            .Set(u => u.UserName, user.UserName)
            .Set(u => u.Media, user.Media),
        new UpdateOptions { IsUpsert = true },
        cancellationToken
    );

Goal

  • Insert the document if it does not exist

  • Update it only if the incoming Version is greater than the stored one

Problem

When a document already exists with a higher version, the filter does not match:

Id == user.Id AND Version < user.Version → false

Because of IsUpsert = true, MongoDB attempts to insert a new document, which leads to:

DuplicateKeyException (same Id)

Question

What is the recommended way to handle this scenario?

  • Is catching and ignoring DuplicateKeyException the correct/expected approach in this pattern?

  • Or is there a better way to implement "update only if version is newer, otherwise do nothing" without triggering an insert attempt?

I'm trying to keep this operation atomic and avoid race conditions, so I'd prefer a single-query solution if possible.

Any guidance or best practices would be appreciated.