Day 25: The Inventory Problem: Concurrency and Race Conditions.

Spring Boot Microservices: From Design to Deployment ~7 min read 15 min hands-on

Welcome back, future architects!

In our journey to build hyperscale microservices, we've explored resilience patterns like Circuit Breakers. Today, we're diving into a problem that, if unaddressed, can derail even the most robust systems: Concurrency and Race Conditions. It's the silent killer of consistency, especially when your system is handling millions of requests per second.

Imagine this: a flash sale for a highly coveted, limited-edition item. Only one unit remains. Two users, Alice and Bob, both click "Buy Now" at precisely the same millisecond. What happens? Does one get it? Or, more terrifyingly, do both get a confirmation, only for your system to realize it just sold an item it doesn't have? This, my friends, is the "Inventory Problem" – the ultimate test of concurrency, leading to a dreaded state called overselling.

The Heart of the Matter: Race Conditions in Action

At 100 million requests per second, even an infinitesimally small chance of a bug becomes a certainty. A race condition, by definition, is a situation where multiple threads or processes access a shared resource concurrently, and the outcome depends on the non-deterministic order of operations.

In our inventory scenario, the shared resource is the stock_quantity for an item. The "non-deterministic order" refers to the exact timing of when the CPU switches between Alice's and Bob's requests.

Let's break down the typical (and flawed) logic for a purchase:

  1. Read Stock: A user's request comes in. The system reads the current stock for itemA. Let's say it's 1.

  2. Check Availability: The system checks if stock_quantity > 0. Yes, 1 > 0.

  3. Decrement Stock: The system prepares to decrement the stock by 1.

  4. Update Stock: The system writes the new stock value (0) back.

This sequence seems logical for a single user. But when Alice and Bob execute these steps concurrently, chaos ensues:

  • Alice's Request:

  • Time T1: Reads stock_quantity = 1.

  • Time T2: Checks 1 > 0 (True).

  • (CPU switches to Bob)

  • Bob's Request:

  • Time T3: Reads stock_quantity = 1. (Crucial: Alice hasn't updated it yet!)

  • Time T4: Checks 1 > 0 (True).

  • Time T5: Decrements stock_quantity to 0.

  • Time T6: Writes stock_quantity = 0.

  • (CPU switches back to Alice)

  • Alice's Request (continued):

  • Time T7: Decrements stock_quantity to 0. (Based on her old read of 1)

  • Time T8: Writes stock_quantity = 0.

Result? Both Alice and Bob successfully "bought" the item, but the stock is 0 (or null, or NaN depending on implementation) when it should be -1 if we were tracking actual sales, or an error for one of them. This is overselling. You've promised two items when you only had one. This leads to customer complaints, refunds, and a damaged reputation – a nightmare for any business, let alone a hyperscale e-commerce giant.

Our Mission: Exposing the Vulnerability

Keep going with the full lesson

The rest of this lesson β€” plus its implementation guide, runnable scripts and source code β€” is included with the course or an All Access plan. Create a free account to start the free lessons in every course.

Already a member? Sign in