Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,130 | Comments: 45,558

filter by tags archive

From the mailing list: Concurrency Checks for Related Unchanged Documents

time to read 3 min | 515 words

We got the following question on the mailing list:

…say you have reference data in one document like prices, formulas, etc.

When the user is editing or creating a document you would like to ensure that their edits are based on the current info at the time of edit.

So the document being edited or created is dependent on the other reference document and the commit should raise a concurrency error if that reference document has changed in between the time the edit started and it is committed.

Of course the reference document is not changed with the document being edited/created.

This question is interesting enough to be worth a blog post. Mostly because this was my reaction when I read the post.

Basically, the premise is wrong. The user have a document like “config/tax-rates”, and when they create an order, they need to make sure that the tax rate hasn’t changed. I am assuming here that “time between edit started & committed” is relatively low, counted in milliseconds, and that there isn’t any human involvement in this process.

The reason this is wrong is the following sequence of events (T+1 is time + 1 ms):

Scenario #1 Scenario #2
  • T +0 – read referenced doc
  • T +1 – create order
  • T +2 – config/tax-rates changed
  • T +3 – save order
  • T +4 – concurrency error because the config/tax-rates changed
  • T +0 – read referenced doc
  • T +1 – create order
  • T +2 – save order
  • T +3 – save order completed
  • T +4 – config/tax-rates changed

According to the question above, both scenarios are absolutely correct ways for the system to behave. In practice, scenario #2 is wrong (probably).

Udi Dahan has wrote about this a lot, but I can’t find the appropriate article at this time. Update: http://www.udidahan.com/2010/08/31/race-conditions-dont-exist/

If it actually matter enough for scenario #1 to require an error, scenario #2 is also invalid. This isn’t a technical issue, it is a business issue. If you failed to update the tax rate after you were notified, you are responsible for it, right? Except that there is no way that this works. Tax changes usually take place at midnight, and are announced several days / weeks in advanced, at a minimum. And even if you were in a total news blackout, you are still responsible for the rate change, even if you never heard about it.

The way this is setup is simply wrong. You don’t try to stop orders from being processed, because you are going to miss the just completed order. Instead, you are going to do compensation logic to fix any changes that apply.

You can also tell that this is the case by the fact that this is actually pretty hard to do. Documents are independent from one another. The best way to work with such a scenario is to record the time (or the etag) when you made a decision based on a related document, then at a later point in time, you can make a decision based on whatever it changed, how old it is, etc.

That gives you proper frame of mind, not trying to count milliseconds.



Domain events

Kyle Szklenski

Incidentally, this is exactly the kind of excellent post I love to see from you. Informative and very pragmatic.

Sounds like an "eventual" model for consistency, of sorts.

João Bragança

ValidFrom / ValidTo for relatively static things like tax rates...

Miguel Lira

Ayende, Great post. I agree this is a business issue - not a technical one.

However, as you pointed out you are assuming the duration between edit and commit is in milliseconds and does not involve user interaction yet the problem outlined in the mailing list is a scenario that involves a longer time between the start of the edit and the actual commit.

What if the user is creating a report based on prices/formulas and those values change on her before she completes the report? If you don’t stop the report from being stored, at the very least it should be considered invalid. Whether that reconciliation is done just prior to saving the report or the next time you read it is a business decision.

Kijana Woodard

@Miguel - I'll stipulate to your scenario. When the user "posts the report", you can do a "validation check" to make sure that the hash/etag of the reference data is still the latest. If it's not respond to the user with appropriate messaging.That's pretty straight forward code.

The only scenario remaining after that is the one outlined above in this post.


Kijana, so where's that 'wrong way'? I don't see anything wrong about your example.

Comment preview

Comments have been closed on this topic.


  1. How to waste CPU and kill your disk by scaling 100 million inefficiently - 15 hours from now
  2. RavenDB Conference 2016–Slides - about one day from now

There are posts all the way to Jun 01, 2016


  1. The design of RavenDB 4.0 (14):
    26 May 2016 - The client side
  2. RavenDB 3.5 whirl wind tour (14):
    25 May 2016 - Got anything to declare, ya smuggler?
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats