Shopify just did something that would make most engineers do a double-take: they replaced Redis with MySQL for their inventory reservation system, and it scaled better. The story hit 86 points on Hacker News with 48 comments because it challenges one of the most common assumptions in modern backend architecture: if you need fast, high-throughput operations, you need Redis. As it turns out, you don't always need Redis. Sometimes you need better engineering. The Problem: Inventory at Shopify Scale Shopify processes millions of orders per day. Every order involves inventory reservations — temporarily holding stock while a payment is processed, then either committing or releasing the hold. This is the classic "inventory reservation" or "soft hold" pattern that any e-commerce platform needs. The requirements are brutal: High throughput: Thousands of reservation operations per second during peak events like Black Friday Low latency: Inventory checks must be fast enough to not slow down checkout Consistency: You can't oversell inventory. Race conditions are unacceptable. Durability: A reservation must survive a crash TTL management: Reservations expire after a timeout if not committed Redis seems like the obvious choice. It's in-memory, it has TTL support, it's fast. And that's what Shopify was using. Why Redis Wasn't Working The problem wasn't Redis's speed — it's fast. The problem was operational complexity. When you use Redis for critical state (not just caching), you introduce a whole new class of problems: Two data stores to keep in sync: Your primary data is in MySQL, your reservation state is in Redis. What happens when they disagree? Durability concerns: Redis persistence (AOF, RDB) is not the same as a database's ACID guarantees. Data loss is possible. Operational overhead: You're running and monitoring two systems instead of one. Consistency models: Redis is single-threaded per instance, but sharding introduces its own complexity. And Redis Cluster's consistency model is not the same as a relational database's. Cost: Running a Redis cluster with sufficient replicas and memory is expensive, especially when the data is also in your database. Shopify's team realized that the Redis layer was adding complexity without solving a problem that MySQL couldn't solve itself — if you used it correctly. The MySQL Solution The key insight was that MySQL's InnoDB engine, when properly tuned, can handle the reservation workload. The approach: 1. Row-Level Locking Instead of Key-Value Operations Redis uses atomic operations on keys. MySQL InnoDB uses row-level locking. For inventory reservations, the contention is on specific product rows — exactly the pattern row-level locking handles well. By designing the schema so that reservation operations only touch the rows they need, MySQL can achieve high concurrency. 2. SELECT ... FOR UPDATE with Skip Locked MySQL 8.0's SKIP LOCKED feature is the secret weapon. It allows queries to skip rows that are locked by other transactions, which is perfect for queue-like patterns and reservation systems. Instead of blocking, transactions just skip the locked rows and process the next available ones. SELECT * FROM inventory_reservations WHERE product_id = ? AND status = 'available' FOR UPDATE SKIP LOCKED LIMIT 1; Enter fullscreen mode Exit fullscreen mode This is the same pattern that powered Postgres's success in queue implementations — and MySQL can do it too. 3. TTL via Scheduled Cleanup Redis has built-in TTL. MySQL doesn't — but you can achieve the same effect with a scheduled cleanup job that marks expired reservations as released. The tradeoff is that expired reservations take up space until the cleanup runs, but if cleanup is frequent enough (every few seconds), the practical impact is minimal. 4. Transactional Integrity The biggest win: reservations and inventory updates are now in the same transaction. If the payment fails, the reservation release and the inventory restoration happen atomically. No more distributed consistency issues between Redis and MySQL. The Results Shopify reported that the MySQL-based system scaled to handle their peak traffic without the operational overhead of maintaining a separate Redis cluster. The latency was comparable, and the consistency guarantees were stronger. The key metrics: Throughput: Sufficient for Black Friday-level traffic Latency: Comparable to Redis for the specific reservation workload Operational cost: Significantly reduced (one system instead of two) Consistency: Strong (ACID transactions instead of eventual consistency) Durability: Database-grade (no Redis persistence concerns) When You Should Still Use Redis This doesn't mean Redis is dead. Redis is still the right choice for: Pure caching: When the data exists elsewhere and loss is acceptable Session storage: When you need fast reads and can tolerate some loss Real-time analytics: When you need sub-millisecond reads on counters and sets Pub/sub: When you need a lightweight message broker Rate limiting: When you need atomic counter operations at high throughput The distinction is: use Redis when you can afford to lose the data, not when it's your source of truth. What This Means for Your Architecture The lesson from Shopify's migration is not "MySQL is better than Redis" — it's that the default choice is often wrong, and the right choice depends on the workload. Before reaching for Redis as a solution, ask: Do I actually need sub-millisecond latency? Or is 1-5ms good enough? Can I afford to lose this data? If not, you need it in a durable store anyway. Am I adding Redis to solve a problem my database already solves? Row-level locking, SKIP LOCKED, and proper indexing might be all you need. What's the operational cost of running two systems? More moving parts means more failure modes. Could I use my database's built-in features? PostgreSQL and MySQL both have features that handle patterns people commonly reach for Redis to solve. The Bigger Trend: Reclaiming the Database Shopify's migration is part of a broader trend: engineering teams are pushing more logic into their databases and simplifying their stacks. We've seen the same pattern with: Companies moving from microservices back to modular monoliths Teams replacing message queues with database-backed job systems Developers using Postgres LISTEN/NOTIFY instead of Redis pub/sub Organizations dropping Elasticsearch and using PostgreSQL full-text search The motivation is always the same: fewer moving parts, stronger consistency, lower operational cost. The tools haven't changed — our understanding of them has. When the database you already have can do the job, adding another system is technical debt, not architecture. Based on Shopify Engineering's blog post. Discussion on Hacker News.
Shopify Replaced Redis With MySQL for Inventory Reservations — and It Scaled Better
Full Article
Original Source
Read the full article at Dev →KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.