Having gone the Magento 2 web store live, we’ve faced some troubles. When there’s high demand for goods, oversell happens. The record oversell number on live was -17. With the help of tests, we managed to get -81. The business logic of our web store is based on sales, that’s why the bug was rather crucial for us. Actually, it was clear that the problem was in the method responsible for products write-off:
When refactoring, we paid attention to the following line:
$stockItem = $this->stockRegistryProvider->getStockItem($productId, $websiteId);
The following method should also be considered:
* @param int $productId
* @param int $scopeId
* @return StockItemInterface
public function getStockItem($productId, $scopeId)
return isset($this->stockItems[$productId][$scopeId]) ? $this->stockItems[$productId][$scopeId] : null;
Now it’s clear that stock can be cached in PHP while script running. Since the stock is used when placing an order, so stock in the method
\Magento\CatalogInventory\Model\StockRegistryStorage::getStockItem is taken from cache and if a lot of people are trying to make a purchase, so some “place order” can start simultaneously. Our situation has made worse because of our customers represented by bots which bought all goods within minutes.
Having found out the reason, it was easy to solve the issue. We clear cache with the method \Magento\CatalogInventory\Model\StockRegistryStorage::removeStockItem, and do it not always, but when the following method is called \Magento\CatalogInventory\Model\ResourceModel\Stock::lockProductsStock. Usually, it is called before stock check and place orders. If you’re not interested in writing your own plugin, you can use the module by following the link https://github.com/Galillei/magento2-belvg-concurrent-checkout-fix. We’ve used the module for a year and no longer faced oversell.