Postpone business scenario processing cost-efficiently with Azure Service Bus
During one of the recent Reenbit projects, our client asked for a particular business case implementation with special requirements. And as you might have already guessed from the title, the main point was about cost efficiency regarding infrastructure usage.
The system we were working on is an online shop, and as usual, users must be able to select products they’re planning to buy and add them to the basket first.
When analyzing production workflows, our client has noticed that people often add something to the basket and don’t take it any further. The point is, that when a product appears in the basket, it changes its status to “reserved”, leading to the updated quantity in stock. So, what if we have ten products in stock and ten people behave as described above? Correct, the 11th one will receive a message that the desired product is not available in stock anymore, which is basically not true, as we’re not 100% sure the previous ten people will finally make a purchase and the product in their baskets can stay there forever.
Hunt for possible solutions
As a result, the requirement was to automate the process of cleaning people’s baskets and updating stock quantities back to their original numbers so that other users are not affected. And all of this should be happening in a configured time period (e.g., the purchase hasn’t been made for 30 minutes after getting added to the basket).
“Undoubtedly, the Azure Service Bus is one of the most popular Azure messaging services. But many people have only a basic understanding of it without knowing its special features.”
At first sight, the feeling was that we needed to develop a dedicated background process which periodically (depending on time period configurations) polls our ordering system and tracks the state of current baskets. And, of course, that party was expected to be deployed on its own infrastructure so that the central ordering system is offloaded and responsible only for serving orders, which is a critical part of the business.
The existing system runs in Azure Cloud, so the first thing we started looking at is what this cloud provider can give us. And as it always happens with clouds, there are many options to choose from. This article is not about a deep dive into background jobs in Azure, but for those who are interested, there is a helpful article containing most of the things in one place here.
If we get back to our initial requirement regarding cost efficiency, the dedicated infrastructure used 24/7 couldn’t be our choice. We could decide to use schedule-driven triggers (timer trigger with recurring schedule), but this was not the best option as timers execute even when people are not ordering anything (Azure still calculates costs for timers’ execution duration).
We kept on researching and switched to event-driven triggers. Undoubtedly, the Azure Service Bus is one of the most popular Azure messaging services. But many people have only a basic understanding of it without knowing its special features. Spoiler alert: Azure Service Bus supports Scheduled Messages! It means we not only send a message to a queue/topic and expect it to be processed as soon as another service picks it up, but we can also decide to postpone sending a message for a specific time in future. And, what’s cool, it’s all managed by Azure, and no additional development is required. To get more insights, you can look here.
With that being said, now we’re in a much better position for an acceptable solution for the scenario described at the beginning. In the event a user adds a product to the shopping basket, the system can send a message to the service bus queue/topic and ask the service bus to “actually” send that message for processing in 30 minutes. When this time comes, the Service Bus consumer will pick that message up, check the status of the product from the basket and, depending on what it says, will either stop processing (if an order has been completed) or remove that product from the basket (if it still was there). And, what’s highly beneficial here, messages will only be sent/processed when human actions occur (infrastructure is being used only when required, which leads to lower costs) as opposed to timers/jobs that run regardless of users’ activity.
All of this can be visualized with a simple flowchart diagram:
The first note (on the diagram) mentions that Service Bus returns a sequence number, so why do we even need that if it’s not used anywhere?
Here one more “bonus” feature arrives: scheduled messages can be cancelled before being processed!
With that, we can optimize our solution to avoid Azure Function execution if the order has already been completed/paid. After scheduling a message and getting the value for the sequence number, we can store this number in a database and then send a cancellation request if the order is completed earlier than x minutes. As a result, the previously scheduled message will never get processed, leading to a much shorter overall execution time of Azure Function (lower cost if we are on the consumption plan) and fewer data queries sent to the main system. It just can’t be better!
Just to summarize, the proposed solution can be applied to different scenarios where “temporary reservation of things” takes place. Two more examples come to mind:
- booking a seat in the cinema, which of course can’t stay booked forever;
- reserving a table in a restaurant and not appearing there before, let’s say, ‘presence check in’ at an agreed upon time.
The system can take care of it and automatically release the reservation.
We hope that was interesting and you can use this neat and simple solution in the future. Or you can trust the Reenbit cloud engineering team with any challenge you’re facing – just drop us a line!