📖 Read the full breakdown: https://www.hellointerview.com/youtub...
Shopify runs $5.1M in sales per minute at Black Friday peak, and every one of those checkouts has to reserve inventory without overselling. For years that ran on Redis. They moved it to MySQL.
Not because Redis was slow. Redis handled the concurrency fine. The problem was that reservations and the inventory ledger lived in two different systems, so no single transaction could cover both, and every failure mode came out of that seam. MySQL 8's SKIP LOCKED made one row per unit viable, which closed it.
🔎 More In the Wild breakdowns: https://www.hellointerview.com/youtub...
📄 Shopify's original post: https://shopify.engineering/scaling-i...
CHAPTERS
0:00 Why this post is worth your time
0:42 Overselling vs. underselling
1:24 What a reservation actually is
1:54 The Redis design, one key per item
3:38 Expiry, and the cron job that cleans up
4:14 Making it atomic with a Lua script
5:44 The bug you can't fix, two systems and one transaction
6:32 Moving it to MySQL, and hitting row contention
7:48 SKIP LOCKED
8:11 One row per unit
8:52 The row explosion problem
10:21 Refilling the pool on the reserve path
12:12 Takeaways
📖 Read the full breakdown: https://www.hellointerview.com/youtub...
Shopify runs $5.1M in sales per minute at Black Friday peak, and every one of those checkouts has to reserve inventory without overselling. For years that ran on Redis. They moved it to MySQL.
Not because Redis was slow. Redis handled the concurrency fine. The problem was that reservations and the inventory ledger lived in two different systems, so no single transaction could cover both, and every failure mode came out of that seam. MySQL 8's SKIP LOCKED made one row per unit viable, which closed it.
🔎 More In the Wild breakdowns: https://www.hellointerview.com/youtub...
📄 Shopify's original post: https://shopify.engineering/scaling-i...
CHAPTERS
0:00 Why this post is worth your time
0:42 Overselling vs. underselling
1:24 What a reservation actually is
1:54 The Redis design, one key per item
3:38 Expiry, and the cron job that cleans up
4:14 Making it atomic with a Lua script
5:44 The bug you can't fix, two systems and one transaction
6:32 Moving it to MySQL, and hitting row contention
7:48 SKIP LOCKED
8:11 One row per unit
8:52 The row explosion problem
10:21 Refilling the pool on the reserve path
12:12 Takeaways