Magento – Stock control race condition between checkout and payment completion

checkout

If two users simultaneously attempt to purchase the last item from an online store, we either have an opportunity for a race condition, or an opportunity for a DOS attack on the store.

Specifically, I am using Magento and Worldpay payment engine, but I see the problem as a more general one where a third party payment gateway is used.

Consider the two scenarios

  1. Stock is deducted when an order is placed OR…
  2. Stock is deducted when a payment is received.

In scenario 1, we have the following problem. If the payment is not completed, the item still goes out of stock. This allows an attacker to order everything without paying for it – of course the item will not be dispatched, but stock control will prevent any legitimate users from ordering the item. The problem has to be fixed manually, when it is noticed, during office hours.

There are settings in Magento to limit the number of items that can be ordered, but this isn't really useful for items where there are only a few in stock – and we might want to sell all of them to legitimate purchaser (ie not say "you can only have 1")

It doesn't necessarily have to be a deliberate attack either. If the user has trouble navigating the payment gateway's website due to a browser issue they may give up – or they may start the process again further depleting stock.

So the other option, scenario 2 leads us to a race condition. If two users both get to the checkout with the last item, they can both order it and carry onto the payment gateway website, because at that stage the stock has not been deducted. And then they both pay, but there is only one item available.

As far as I can make out, there is only a payment notification protocol, not a "is this item still in stock" protocol.

So I was wondering how people generally deal with this problem, and in particular what Magento / Worldpay configurations could be used to alleviate the issues.

The best fit I could think of is some sort of timeout on payment, which puts the item back in stock. This would require a payment timeout both at the Magento end and at the Worldpay end, but I can't see any method of doing that at either end.

Best Answer

In the various bits of contracting and consulting I've done, the solution is not to solve this problem. The general thinking is

  • It happens less often than you'd think

  • When it does happen, it's easier to take both orders and fix things on a business level

Fixing this on a business level means waiting to fulfill the second order until more stock comes in, or if more stock isn't coming you cancel the customer's order and send an apologetic email with an optional coupon or some other low cost fringe benefit so they don't feel bad.