We’ve had a few questions regarding the inner workings of Reserved Stock Pro (RSP) – This doc is a deep dive for advanced users.
How does Reserved Stock Pro work?
Our Reserved Stock Pro plugin uses a custom database table called
rsp_reserved_stock to track stock reservations. We’ve decided to use a custom database table to provide the best performance and flexibility possible. Other plugins may store reservations via product meta.
What’s tracked in the database table?
There are a few columns with data for tracking reservations.
- customer_id – The customer ID will be an auto generated ID for guests. If the customer is logged in, it it will be their WordPress user ID.
- product_id – The ID of the product that has been reserved.
- timestamp – Timestamp of when the product was added to cart. This is not used for any calculations at the moment.
- expiration – The timestamp when the reservation expires. This timestamp may be updated as the customer updates their cart.
- order_id – If the customer proceeds through the checkout, WooCommerce will create a pending order. Reserved Stock Pro uses the order ID to track when WooCommerce reduces the product stock for the order. This happens at different times depending on the payment gateway.
How are stock reservations tracked?
The stock reservations are tied to the customer ID and expiration date. Therefore, only the customers who have reserved the product stock can purchase the product.
As a simplified explanation, the plugin compares the stock quantity and the reserved quantity to check what’s available for other customers. If there’s no available stock left, then other customers cannot add the product to the cart.
Depending on your theme, the “Add to cart” buttons will be disabled. If the customer can still click the “Add to cart” button, the request goes through the Reserved Stock Pro validation and a customizable notice will be displayed, letting the customer know that there’s no available stock left.
Reserved Stock Pro handles product reservations together. All stock-managed products are synced and will expire at the same time from the cart. The customer will keep track of their expiration time via a countdown, so they will know exactly how long they have to make their purchase.
Behind the design choice:
Early on, we considered having each product reserved separately. However, this would generally introduce stress for the customer experience. The customer would have to keep track of multiple products leaving their carts at different times, which takes the enjoyment/relaxation out of the shopping experience.
We believe that customers who show an intent to purchase multiple products should be prioritized. After all, our goal is to sell stock, not make it available again as quick as possible.
Reserved Stock Pro will also extend the reservation time for customers who add new products to their cart. The reservation time will be reset using the number of allowed reservation minutes from the settings. The reservation time remains unchanged when customers remove products from their cart or update quantities of products in the cart.
Behind the design choice:
The idea behind this choice is to give customers all the time they need to go through the store and pick the products they desire. If the time doesn’t extend, customers could stress out and not get all the products they originally wanted. We want to reward customers for shopping, rather than making it feel like a race. We believe that customers who show an intent to purchase multiple products should be prioritized.
After all, a common eCommerce goal should be to increase the average order value, not limit customers who are interested in multiple products.
When do reservations expire?
Reserved Stock Pro checks that the current time is less than the customer’s expiration time that’s saved in the database. This allows for quick database queries to find if reservations have expired for the current customer, as well as to find the amount of stock that’s reserved for a specific product.
Reservations are cleaned up early from the database when different actions occur, such as:
- Product has been removed from the cart.
- Product was purchased.
- Product quantity in cart has changed.
- Customer loaded the site after the product expiration date.
- An order with pending payment and reservations is trashed.
Any other expired reservations in the database will automatically be deleted every 12 hours using a WP Cron Job. The scheduled cron job is called
Validation to prevent overselling
Reserved Stock Pro reserves product stock only for simple & variable products. Those products must have stock management enabled, otherwise there is no stock to reserve in the first place.
Reserved Stock Pro includes validation at every step in the WooCommerce purchasing process to determine whether or not the customer can add the product to their cart and purchase.
Actions that trigger validation:
- Attempting to add a product to cart.
- Updating quantity of a product in cart.
- Loading the cart from session (every time a page loads).
- Attempting to checkout.
Reasons validation may fail:
- All stock has been reserved by other customers.
- All stock is sold out.
- Current product reservation has expired.
- Customer doesn’t have the product reserved.
- Customer cannot increase the quantity.
Hooks such as
is_purchasable() are during the actions for the customer session. These hooks is the way Reserved Stock Pro provides WooCommerce with the expected behaviour for each customer session.
The validation constantly happens while the customer triggers different actions on the site. All actions that involve database queries are built prevent the overselling and duplication. This leads us to concurrency.
What about concurrency?
Concurrency means multiple computations are happening at the same time. In this case we’re talking about 1000s of customers. We are interested in what happens when WooCommerce has multiple customers trying to purchase the same product at the same time.
To mitigate concurrency issues the query used to check and reserve stock is performed in a single, atomic operation.
This operation locks the tables so that separate processes do not fight over the same stock. If there were two simultaneous requests for the same stock at the same time, one would succeed, and one would fail.
Guest customers can log in
Guest customers are anyone who has added a product to their cart and hasn’t logged in. Their cart products are reserved under the WooCommerce auto-generated guest ID. Reserved Stock Pro will handle transferring the reservations to an actual WordPress user ID if the customer logs in at any time or creates a new account on the checkout,
WooCommece will create orders with the status of “pending” depending on the payment gateway. One of those gateways is the PayPal Checkout gateway, which we’ll use for the below example.
When a customer is at the last step of the checkout process, they will click “Pay via PayPal” and 3 things will happen:
- The customer will be redirected to finalize the payment on PayPal’s website.
- WooCommerce creates a “Pending” order.
- Reserved Stock Pro tracks the newly created order ID and extends the reservation time using the “Hold Stock Minutes” setting in WooCommerce, or 60 minutes if the mentioned setting is not set.
Why extend the reservations?
- The customer may cancel the payment to choose a different payment option.
- The customer may browse the site in a different tab while finishing the payment.
- The PayPal IPN (Instant Payment Notification) can be slow to mark orders as paid.
When is stock actual stock reduced?
Reserved Stock Pro keeps track of reservations in the custom database table and therefore doesn’t modify the stock inventory in the product’s metadata.
WooCommerce will reduce the product’s stock when the order status changes to “On Hold”, “Processing” or “Completed”. Reserved Stock Pro will delete the reservation for the customer as soon as the customer’s order reduces the actual product stock.