Managing product inventory in e-commerce or high-concurrency systems can be tricky. What happens when 10,000 users try to buy the same product at the same time? Without careful design, you risk overselling, inconsistent stock counts, or database bottlenecks.
Without careful design, you risk overselling β, inconsistent stock counts π€―, or database bottlenecks π.

1. π§ Problem Statement
π Imagine a product with only 5 items in stock π¦.
If 20 people click βBuyβ at the same time πππ, how do we make sure only the first 5 succeed β
and the other 15 get out of stock β?
- MongoDB alone = too slow π’.
- Redis + Lua = lightning-fast β‘ and safe π‘οΈ.
2. π οΈ Core Concepts
- Redis π§ β Super fast in-memory DB (like a sticky note always ready).
- Lua Script π§© β Ensures atomic operations, no interruptions.
- Tokens ποΈ β Each unit of stock is one token in Redis.
- MongoDB π β Keeps long-term order + reservation data.
- Cron Jobs β° β Small background workers that clean up expired reservations.
π Together = a safe stock system ποΈ.

3. π System Flow Diagram
π€ Client (User clicks Buy)
β
βΌ
π’ Node.js (Express API)
β
β 1οΈβ£ Ask Redis for tokens
βΌ
π΄ Redis (Tokens per product)
β
β 2οΈβ£ Lua script reserves tokens
βΌ
π¦ MongoDB
β
β 3οΈβ£ Save Order + Reservation
βΌ
β° Cron Job
β
β 4οΈβ£ Expired order β tokens back
βΌ
π΄ Redis (stock restored)
π Think of Redis as a ticket counter π«, Mongo as the ledger π, and Cron as the cleaning robot π€.
4. ποΈ Token-Based Stock Reservation
When seeding products, you push tokens into Redis:
await client.lpush("product:101:tokens", ["token:1","token:2","token:3"]);
- Each token = 1 unit of stock π¦.
- Buy 2 units β 2 tokens are popped out ποΈποΈ.
- No tokens left β product is sold out π«.
π Super simple & visual = no overselling! π
5. π§© Lua Script for Atomic Reservation
Why Lua? π€
Because if 1,000 users click buy at once π₯π₯π₯, normal loops fail.
Lua = all or nothing π―
-- Reserve tokens in one atomic step
if enough tokens β success β
else β rollback π
π Think of Lua as a bouncer at the door πͺ:
Nobody sneaks in, everything is fair β.
6. π MongoDB Orders & Reservations
Redis is fast but temporary β‘π§ .
So we also save results in MongoDB for safety.
- Order π§Ύ β Who bought what.
- Reservation ποΈ β Which tokens are locked + expiry time β³.
π Mongo is like the history book π so nothing gets lost if Redis resets.
7. β° Handling Expiry with Cron Jobs
What if a user clicks buy but never pays? π³β
- Stock canβt stay locked forever β.
- Solution: Cron Job runs every few seconds π.
- Expired reservations β tokens go back to Redis β»οΈ.
π Cron = the janitor π§Ή cleaning unused tokens.
8. βοΈ Pros & Cons
β Pros
- Super fast β‘ (Redis in-memory).
- Atomic π‘οΈ (Lua prevents race conditions).
- Scalable π (works in flash sales).
β Cons
- More moving parts βοΈ (Redis + Mongo + Cron).
- Must seed tokens correctly ποΈ.
- Sync issues if stock changes outside Redis π.
π But overall β Worth it for high concurrency πͺ.
9. ποΈ Microservice Use
This design works beautifully in a microservice world π:
- Product Service πͺ β Seeds tokens in Redis.
- Order Service π¦ β Handles token reservation + Mongo save.
- Payment Service π³ β Confirms payment, finalizes stock.
π Redis = the shared brain π§ for all services.
10. π― Key Takeaways
- Redis + Lua = safe, atomic stock ops β‘π‘οΈ.
- Tokens = ποΈ simple way to represent stock units.
- Mongo = π history keeper.
- Cron = β° auto cleanup robot π€.
- Perfect for π flash sales, ticketing systems ποΈ, and high-load apps π₯.
π Example Story (Easy to Imagine)
- Product A has 3 items β Redis =
[t1, t2, t3]
. - Alice buys 2 π β gets
[t1, t2]
. - Bob tries 2 β only
[t3]
left β Bob gets β out of stock. - Alice doesnβt pay π¬ β Cron returns
[t1, t2]
to Redis.
π Always fair β , never oversells π«, and self-heals β»οΈ.
π₯ With Redis + Lua, your system can handle 10k+ concurrent buyers without overselling, while MongoDB + Cron ensures long-term consistency.
How do you handle partial inventory reservations if a user tries to buy more than is available in stock? Does the Lua script manage that or is it handled upstream