Sage Nord

← All posts

How Shopify sharded Shop app's Rails backend without stopping the world

Shopify's engineering team published a detailed account of migrating the Shop app's Ruby on Rails backend from a single MySQL database to Vitess, the open-source MySQL sharding layer originally built at YouTube. It's a useful case study, not because sharding is a novel idea, but because of what the team identifies as the actual reason the migration succeeded.

The problem was concrete and familiar to any team that's scaled a monolithic relational database past its comfortable ceiling. Shop app's user base grew fast enough that the database disk reached multiple terabytes, schema migrations on the largest tables started taking weeks, and background jobs were routinely throttled whenever the primary database approached capacity during peak traffic. The team had already split the database into separate logical databases by domain, a common first step, but had exhausted that approach. Going further would mean cross-database transactions and a meaningful increase in application-layer complexity. That's the point at which incremental fixes stop working and an architectural change becomes unavoidable.

Shopify chose Vitess and executed the migration in three phases: first "Vitessifying" the existing MySQL cluster behind Vitess's VTGate proxy with zero downtime, then splitting all tables into three logical keyspaces (users, global, and configuration), and finally sharding the users keyspace by user_id across multiple physical shards. Each phase was designed to be reversible and low-risk on its own, rather than one large cutover.

The part of the writeup worth paying attention to is not the sharding strategy itself, it's how the team made a live, actively-developed Rails codebase safe to shard incrementally. They built custom query verifiers that ran in CI and, later, in production in log-only mode, specifically to catch queries that would break once sharding was in place: queries missing the sharding key, transactions that crossed shard boundaries, joins across keyspaces, and writes issued outside a transaction that touched multiple shards. Rather than trying to manually audit every query in the codebase, the verifiers let the team keep shipping new code throughout the migration while automatically flagging anything incompatible, and the team credits this single mechanism as the biggest factor in the migration's success. Roughly 25 bugs surfaced this way, some of which were significant enough to be contributed back as fixes to the open-source Vitess project.

The measurable result Shopify reports: schema migrations that used to take weeks now take hours, background job throttling caused by database capacity has stopped, and scaling further is now a matter of adding shards rather than another architectural rework.

Why this generalizes: the pattern isn't specific to Shopify, Rails, or even Vitess. Any team facing a monolithic relational database that has outgrown vertical scaling and table-level federation faces the same core problem, how do you migrate a live, actively-written-to system to a sharded architecture without a long freeze on feature development. The answer here, build automated verifiers that encode the new system's constraints and run them continuously against real traffic and real CI, applies whether you're moving to Vitess, Citus, or a custom sharding layer. It turns "audit every query by hand" into "let the system tell you what's wrong," which is the only way this kind of migration survives contact with an active codebase.

Where it doesn't automatically generalize: this approach assumes you can identify a single, dominant sharding key (user_id, in Shopify's case) that covers the vast majority of your data model. Teams whose access patterns don't cluster around one entity, or whose data model resists a clean sharding key without significant remodeling, will find the harder part of this problem is the data model work that has to happen before any verifier can be written.

Source: Shopify Engineering, "Horizontally scaling the Rails backend of Shop app with Vitess".