[email protected]

Prevent overselling with the right stock strategy

Keeping accurate stock levels for your items across all systems is a harder problem than it might first appear. How much revenue are you losing because you do not dare trust your own stock levels and always keep a buffer to be on the safe side?

Anders Ekdahl5 April 2022

In a typical systems landscape for an e-commerce operation, several systems need to know the stock level of your items. Often at least the e-commerce system and WMS/ERP. As soon as the same data exists in several systems there is a risk that data is out of sync. Simply that the stock level in the e-commerce system says one thing while the WMS says another.

Stock levels are not the only data existing in several systems. Often you have product information that first comes from your ERP into your PIM which then goes over to your e-commerce system. The big difference is that this data has a clearer and more one-directional flow. The item is born in the ERP, and when it comes over to PIM, PIM then owns it. The e-commerce system receives the data but it is rarely changed in the e-commerce system. And even in more complex scenarios where different systems own and change the PIM data, it is different fields the different systems own. It is obvious that if you let the same field be changed in several systems at once you have created a nightmare for yourself.

What makes stock levels so much harder is partly that it often has to be updated in several systems, and that there is a time aspect to how valid the data is. When a stock update is sent from one system to another, that stock level may already have become out of date because of other changes that happened.

There are several approaches you can take here to avoid over- or under-selling and have as accurate stock levels as possible.

Option 1: Real-time communication between systems

This option is based on not having stock levels spread across several systems, but instead letting your systems ask the WMS in real time when you need to know the stock level. This option sounds very tempting because there is of course a simplicity in only having the stock in one single system. No risk of clashes, no risk of it becoming out of date.

This is undoubtedly the best option. But it relies on your WMS being built to handle it. And the requirements to be able to handle it are more than you might think.

Firstly, the WMS must then have at least as good scalability characteristics as your e-commerce system. If you launch a big campaign, it is not only the site that has to scale up but also the WMS to be able to handle the increased traffic. But not only that, you have also made yourself entirely dependent on the WMS being up to be able to receive orders in the e-commerce. If the WMS goes down no one can shop. It puts completely different system requirements on the WMS than what it may have been built for.

Even though this option relies on the stock level only existing in the WMS, it is a truth with modification. What it actually means is that the stock is only changed in the WMS. If you for example want your customers to be able to filter away out-of-stock products, then the stock level needs to be in the search engine too. Another requirement on the WMS is thus that it can communicate stock changes incrementally to other systems via events. Many WMS of course support that, but often in less modern ways. The search engine should then not only get product data from the e-commerce system but also stock levels from the WMS. Alternatively, send the stock level to the e-commerce system but only see it as a readable copy.

Advantages

  • It is conceptually nice to know that stock can only be changed in one single system. You minimise the risk of over- or under-selling.

  • Provided your WMS handles the requirements placed on it, it is a healthy architecture to let different systems handle individual parts rather than spread it out.

Disadvantages

  • The WMS becomes a single point of failure for customers to be able to shop.

  • High requirements are placed on the WMS in terms of uptime, scalability and the possibility to expose stock and stock changes in technically modern ways.

  • You may need to build the integration between your e-commerce and the WMS yourself. Depending on which e-commerce system you have, this can be a significant and in some cases even impossible undertaking.

Option 2: Handle and change stock levels in several systems in parallel

This option sounds very complicated at first glance. Several systems changing stock levels independently of each other feels instinctively like it will quickly go wrong. And it is complicated, but it has a number of advantages if you pick the right strategy. What most people do not think about in this solution is that it is very important that only certain updates are sent between systems, and that you send changes rather than the whole stock level. That is, instead of the WMS sending "the stock level is now 100" it should send "the stock level just decreased by 3". The reason is that "the stock level is now 100" is a definitive number and that number will only be true for a certain time. While "the stock level just decreased by 3" is true forever and not dependent on time in the same way.

In a loosely coupled/composable systems landscape you want to communicate between systems in an asynchronous way. Instead of asking a question and waiting for the answer between systems, events are sent. To get as much as possible out of an event-driven architecture, you need to minimise the dependency on when these events are sent and received in time. If for example the order confirmation email is sent as a consequence of an event, it is better if the email is sent ten minutes after the order is placed than not being sent at all. That you design your landscape so that delays cause nothing other than certain flows going a bit slower.

Sending stock changes rather than stock levels is exactly one such thing where sending stock levels can cause errors on delays. For example:

  1. Item A gets a new stock level in the WMS, and the stock is now 10

  2. The stock level syncs over to the e-commerce

  3. An order is placed in the e-commerce with two of item A, and the order is queued to be sent to the WMS

  4. The e-commerce system decrements its stock by two, and now has 8 in its stock while the WMS still has 10

  5. A customer rings at the same time and wants to remove item A from their order, which customer service does

  6. The WMS returns the item to the sellable stock and now sees the stock as 11

  7. The WMS sends to the e-commerce that the stock is 11 and the e-commerce increments the stock from 8 to 11

  8. The order from point 3 comes over to the WMS which decrements to 9 and sends this to the e-commerce

In this case we have asynchronous communication between WMS and e-commerce, and the fact that we send stock levels rather than changes means we risk overselling between points 7 and 8. If at point 7 we had instead sent "the stock should increase by 1", we would have avoided the oversell, because the e-commerce would have had 9 in its stock and the WMS would have had 11 in its stock until point 8 was done and both systems were in sync again.

Sending changes is not the only thing you need to think about here. If you have an e-commerce system that itself maintains and decrements stock when orders are placed, not all changes can be sent to the e-commerce from the WMS because we would then be double-decrementing. For example:

  1. An order is placed in the e-commerce with item A

  2. The e-commerce decrements its stock from 10 to 9

  3. The order is sent to the WMS

  4. The WMS decrements its stock, and now we are diligent and send out a change rather than a number. The WMS thus sends out "item A should be decreased by 1"

  5. The e-commerce receives the message and decrements item A from 9 to 8

In this case we create underselling, which is not quite as bad as overselling but still not good. The way we solve this is either by the WMS sending out a reason for the stock decrease together with the change, or by the WMS simply not sending decreases to the e-commerce that happen because e-commerce orders are placed. The first is preferable, that the message sent contains the reason for the stock decrease. Then the e-commerce can receive the message and itself determine that no adjustment needs to be made.

The reason this is preferable is because we then keep the systems more isolated. If the WMS knows it should not send messages to the e-commerce for e-commerce orders, the WMS takes on responsibility that really does not concern the WMS. If the e-commerce is one day changed so that that message actually is needed, we do not want to have to touch the WMS.

Advantages

  • Isolation and looser coupling between systems gives a healthy systems landscape over time

  • The WMS does not need to be scaled up to handle e-commerce traffic

  • Less is required of the WMS technically in terms of modern APIs and events

Disadvantages

  • More complex, the WMS team and the e-commerce team have to align

  • If you have no event architecture from before, it is a big step to take

  • It is almost inevitable that the actual stock levels over time will differ between WMS and e-commerce. Events can be missed because systems go down, systems can contain bugs, and so on. This approach requires you to be able to do a manual full sync of stock across the whole item register when the warehouse is closed.

Option 3: Hold reservations in the e-commerce instead of decrementing stock

This option is an extension of option 2, and opens up some new possibilities and safety but is technically more complex.

One problem with sending stock changes rather than definitive numbers is that it is never entirely safe to do a full sync from the WMS to the e-commerce. At least not without shutting down the e-commerce to stop taking more orders. The only occasion when it is safe is if you know all orders are sent from the e-commerce and all message queues are empty. If you have the Nordics as customer base, it may be feasible to do it at night, but the more global you become, the worse it scales.

In this option we allow definitive stock levels again, that the WMS sends "100 in stock for item A" instead of "item A should be decreased by 1". Ideally the message from the WMS should contain all of that information. That is, total stock, change and reason for the change. Then the receiving system can decide for itself.

The reason we allow it again is that in this option we do not decrement the stock when an order is placed in the e-commerce, but instead create a stock reservation linked to the order. And the effective stock from the e-commerce's perspective is the WMS's stock minus reservations the WMS has not yet received. The flow instead becomes like this:

  1. Both the e-commerce and the WMS have stock 10 for item A

  2. Order O1 is placed in the e-commerce with item A

  3. A stock reservation for order O1 is created in the e-commerce that says 1 of item A is reserved

  4. The effective stock for the e-commerce becomes 9 even though the stock is still 10 just as in the WMS

  5. The order is sent to the WMS

  6. The WMS decrements its stock and sends out a message saying order O1 has been received

  7. The e-commerce releases the reservation on O1

  8. Here we can then choose whether we want the e-commerce itself to decrement its stock when the reservation is released, or if the WMS sends out a decrease. If we let the WMS do it, it is very important that that message comes before or at the same time as the order message. Otherwise we release the reservation, which increases the effective stock until we get the message that it should be decremented.

The main point here is that even though we let both the e-commerce and the WMS decrement stock, we have broken it up into two parts where the two systems each change their own part. That way we remove risks with timing of when the different systems change the stock.

Advantages

  • This option has all the advantages option 2 has

  • We have reduced the risk of stock levels differing between WMS and e-commerce because we separate stock and reservations and let the WMS control the stock

  • Reservations make it easier to handle cancelled orders because we know how a cancelled order affects stock. If there is a reservation, it should be released. If there is no reservation, we do not need to do anything. Without reservations it can be unclear whether a cancelled order should affect the stock.

  • A full sync of the WMS's stock to the e-commerce can be run at any time because we have separated stock and effective stock in the e-commerce.

Disadvantages

  • Requires basically your own implementation of this. I have so far not come across any e-commerce platform that supports this flow (correct me if I am wrong).

What should I pick?

These options are listed in ascending order of complexity but also in ascending order of increased safety. None of them is right or wrong, and all three of them can help you sleep well at night with the right implementation.

Option 1 is primarily if you do not have large amounts of traffic, or if your WMS can handle it and is built for it. It is a strategy that often suits either smaller e-commerce operators without large amounts of traffic, or very large e-commerce operators with a WMS built to be able to handle it.

Option 2 is a model that can be fitted into most e-commerce systems and WMSs, and a good start when you want to decouple your systems from each other.

Option 3 primarily suits you who are prepared to build your own solutions to stitch together your systems, because this option does not exist out of the box.

Anders Ekdahl

Author

Anders Ekdahl

Anders is the mind behind the technical frameworks that have taken the likes of Lyko and Nordic Nest to the next level. In his role as CTO of Sweden's leading e-commerce consultancy, he has led more than 200 developers to success, combining technology, strategy and business value in a distinctive way.

Related articles

Technical debt: when 'we will fix it later' becomes 'why is everything on fire?'

Technical debt is more than a technical concept, it is a business-critical reality that affects everything from time-to-market to customer experience. In e-commerce, where every millisecond and every click counts, the choices you make in your technical platform can have far-reaching consequences. When quick fixes are prioritised over long-term durability, an invisible but growing debt is built up. It affects not only development speed and stability, but at worst can slow the company's ability to innovate and compete. To face the future the right way, technical debt has to be understood, quantified and managed as the strategic investment it actually is.

John Järpling