The Rails Monolith That Refused to Die
In 2004, when Tobias Lütke started building Shopify, he chose Ruby on Rails for a simple reason: it was the fastest way to get a working e-commerce platform to market. What he didn’t know was that this decision would create one of the most fascinating architectural evolution stories in modern software development—a monolith that grew to serve 600,000+ merchants and process billions of pounds in transactions, all while maintaining the original codebase.
Today, Shopify processes over £200 billion in gross merchandise volume annually, serving everything from single-person startups to massive enterprises like Gymshark and Allbirds. But here’s what’s truly remarkable: the core platform still runs on the same Ruby on Rails application that Lütke wrote 20 years ago, with all his original commits still in the version control history.
This isn’t a story about technical debt or legacy systems holding back innovation. Instead, it’s a masterclass in how to evolve a monolith into a modern, scalable platform while maintaining the development velocity that made it successful in the first place. The journey reveals fundamental truths about when to embrace microservices and when to stick with what works.
What You’ll Learn About E-Commerce Platform Architecture
This deep-dive will reveal how Shopify’s engineering team solved the unique challenges of e-commerce at scale, from handling Black Friday traffic spikes to managing thousands of third-party integrations. You’ll discover why they chose to keep their Rails monolith while building microservices around it, how their MySQL sharding strategy enables horizontal scaling, and why their approach to frontend architecture has evolved from server-side rendering to React and GraphQL.
You’ll also learn about the operational challenges of running a platform that serves millions of customers worldwide, from their CI/CD pipeline that runs 100,000+ unit tests to their sophisticated monitoring and alerting systems. Most importantly, you’ll understand how to apply these lessons to your own e-commerce or platform development projects.
The Monolith That Grew Up: Rails at Enterprise Scale
When most companies reach Shopify’s scale, they face a difficult choice: rewrite the monolith in a more “enterprise-friendly” language, or break it into microservices. Shopify chose a third path: keep the monolith but evolve it into a platform that can support both rapid development and massive scale.
The core Shopify application remains a single Rails application with hundreds of thousands of lines of code. But this isn’t the monolithic nightmare that many developers fear. Instead, it’s a carefully architected platform that provides shared services, common patterns, and consistent APIs across the entire organisation.
The monolith handles the core e-commerce functionality: product catalogues, shopping carts, checkout processes, and order management. These are the features that every merchant needs, and they benefit from being in a single codebase where changes can be made quickly and consistently.
But around this core, Shopify has built hundreds of specialised Rails applications. These aren’t microservices in the traditional sense—they’re domain-specific applications that handle specific business functions. The Shipping app talks to various shipping providers, the Identity app handles single sign-on across all Shopify stores, and the App Store manages third-party integrations.
This hybrid approach provides the best of both worlds: the development velocity of a monolith for core features, and the flexibility of microservices for specialised functionality. It’s a pattern that many companies are now adopting, but Shopify was one of the first to prove it could work at massive scale.
The Data Layer: MySQL Sharding at Global Scale
One of the most critical decisions in Shopify’s architecture was how to handle data at scale. With 600,000+ merchants, each with their own products, customers, and orders, traditional database scaling approaches would have failed completely. The solution was a sophisticated MySQL sharding strategy that isolates each merchant’s data while enabling horizontal scaling.
The key insight was that e-commerce data is naturally partitioned by merchant. A customer’s order from one store has no relationship to their order from another store, so there’s no need to keep all data in a single database. This natural partitioning made sharding not just possible, but optimal.
Shopify’s sharding strategy works by assigning each merchant to a specific database shard. When a request comes in, the application determines which merchant it’s for and routes the database queries to the appropriate shard. This approach provides several critical advantages:
First, it enables horizontal scaling. As the platform grows, new shards can be added without affecting existing merchants. Second, it provides natural isolation—one merchant’s heavy usage doesn’t affect another’s performance. Third, it simplifies backup and recovery—each shard can be backed up independently.
The sharding strategy also enables sophisticated caching. Since each merchant’s data is isolated, Shopify can use aggressive caching strategies without worrying about data consistency across merchants. Memcached is used for key-value storage, while Redis handles background jobs and queues.
But perhaps most importantly, this approach enables Shopify to offer different service levels to different merchants. A small startup can run on a smaller shard with basic resources, while a large enterprise can be moved to a dedicated shard with premium hardware and additional features.
Frontend Evolution: From Server-Side Rendering to React and GraphQL
Shopify’s frontend architecture has undergone a remarkable evolution over the past two decades, reflecting the broader changes in web development while maintaining the performance and reliability that merchants demand. The journey from server-side rendering to modern React applications reveals important lessons about when to adopt new technologies and when to stick with what works.
The original Shopify admin interface was built with server-side rendering, using Ruby templates to generate HTML on the server. This approach provided excellent performance and SEO benefits, but it limited the interactivity and user experience that modern web applications require.
In 2013, Shopify experimented with a custom single-page application framework called Batman.js, but quickly realised that building and maintaining a custom framework was more effort than it was worth. They moved back to server-side rendering with vanilla JavaScript, focusing on performance and reliability over cutting-edge features.
But as the frontend ecosystem matured, Shopify recognised that they needed a more sophisticated approach. In 2018, they began migrating the admin interface to React and TypeScript, using GraphQL APIs to communicate with the backend. This migration wasn’t just about adopting new technologies—it was about enabling new capabilities that were impossible with server-side rendering.
GraphQL proved to be particularly valuable for Shopify’s use case. The admin interface needs to display complex, interconnected data (products, variants, inventory, orders, customers), and GraphQL enables efficient, client-driven queries that only fetch the data that’s actually needed. This approach reduces server load while improving user experience.
The migration to React also enabled Shopify to build more sophisticated user interfaces, with real-time updates, complex data visualisations, and seamless integrations with third-party services. But perhaps most importantly, it enabled them to maintain the development velocity that made the platform successful in the first place.
Infrastructure and DevOps: Kubernetes at E-Commerce Scale
Shopify’s infrastructure has evolved from a single data centre to a global cloud platform running on Google Cloud Platform. This evolution required not just new technologies, but entirely new approaches to deployment, monitoring, and operations that could handle the scale and complexity of a global e-commerce platform.
The platform runs on Google Kubernetes Engine (GKE), with hundreds of services orchestrated across multiple regions. This containerised approach enables rapid deployment, automatic scaling, and easy rollbacks—capabilities that are essential for a platform that needs to handle traffic spikes during peak shopping periods.
The CI/CD pipeline is built around BuildKite, which runs thousands of parallel tests on private build agents. This approach enables Shopify to maintain a fast feedback loop while running comprehensive test suites that include the 100,000+ unit tests in the main Rails application.
Deployments are managed through ShipIt, an internal orchestrator that handles the complex task of deploying changes across hundreds of services. The system uses feature flags to enable gradual rollouts and instant rollbacks, ensuring that new features can be tested safely before being exposed to all merchants.
Monitoring and observability are built into every layer of the platform. The team uses sophisticated alerting systems that can detect issues before they affect merchants, and comprehensive logging that enables rapid debugging when problems do occur.
Implementation Insights: What This Means for Your E-Commerce Platform
Shopify’s architecture provides several key insights for e-commerce platform development. First, the hybrid approach of keeping a monolith for core functionality while building microservices for specialised features can provide the best of both worlds—development velocity and scalability.
Second, the MySQL sharding strategy demonstrates that traditional databases can scale to massive levels when the data is naturally partitioned. This approach is particularly valuable for multi-tenant platforms where each tenant’s data is independent.
Third, the frontend evolution shows that it’s possible to adopt new technologies gradually while maintaining performance and reliability. The key is to focus on the capabilities that new technologies enable, not just the technologies themselves.
Finally, the infrastructure approach demonstrates that modern DevOps practices can be applied to legacy applications, enabling them to benefit from cloud-native capabilities without complete rewrites.
Next Steps: Applying These Lessons to Your Platform
If you’re building an e-commerce platform or any multi-tenant application, consider Shopify’s hybrid approach. Start with a monolith for core functionality, but design it to support microservices for specialised features. This approach can provide the development velocity you need to compete while maintaining the scalability you need to grow.
For data architecture, consider whether your data is naturally partitioned. If it is, sharding might be a better approach than trying to scale a single database. The key is to understand your data access patterns and design accordingly.
For frontend architecture, focus on the capabilities you need rather than the technologies you want to use. Server-side rendering might be sufficient for your use case, or you might need the interactivity that React provides. The key is to make these decisions based on user needs, not technical preferences.
Finally, invest in infrastructure and DevOps capabilities from the beginning. The operational overhead of running a platform at scale is significant, and it’s much easier to build these capabilities gradually than to retrofit them later.
Shopify’s architecture demonstrates that it’s possible to build a successful platform using “boring” technologies like Ruby on Rails and MySQL, as long as you’re willing to invest in the operational capabilities needed to run them at scale. The key is to focus on solving real problems for real users, not on using the latest and greatest technologies.
Sources:

