Upgrading Shopify to Rails 5

Today, Shopify runs on Rails 5.0, the latest version. It’s important to us to stay on the latest version so we can improve the performance and stability of the application without having to increase the maintenance cost of applying monkey patches. This guarantees we would always be in the version maintained by the community; and, that we would have access to new features soon. Upgrading the Shopify monolith—one of the oldest and the largest Rails applications in the industry—from Rails 4.2 to 5.0 took us nearly a year. In this post, I’ll share our upgrade story and the lessons we learned. If you're wondering how the Shopify scale looks like or you plan a major Rails upgrade, this post is for you.

Kir Shatrov
8 min readintermediate
--
View Original

Overview

This article details Shopify's upgrade from Rails 4.2 to Rails 5.0, highlighting the challenges faced, the preparation steps taken, and the strategies employed to ensure a smooth transition while maintaining backward compatibility.

What You'll Learn

1

How to prepare a large Rails application for a major version upgrade

2

Why maintaining backward compatibility during an upgrade is crucial

3

How to implement a dual Gemfile strategy for Rails upgrades

4

When to use CI pipelines to support multiple Rails versions

Prerequisites & Requirements

  • Understanding of Rails application architecture and gem dependencies
  • Experience with large codebases and version control systems(optional)

Key Questions Answered

What steps did Shopify take to upgrade from Rails 4.2 to 5.0?
Shopify prepared for the upgrade by rewriting code to eliminate deprecated features and ensuring all 370 gem dependencies were compatible with Rails 5. They implemented a dual Gemfile strategy to maintain compatibility during the upgrade process.
How did Shopify handle the challenges of a large codebase during the upgrade?
Shopify formed a SWAT team of senior Rails developers to address over 1000 failing tests on Rails 5. They used a dual CI pipeline to test both Rails versions simultaneously, which helped manage the complexity of the upgrade.
What were the performance issues encountered after upgrading to Rails 5?
After upgrading, Shopify noticed that ActiveSupport::Deprecation#warn was allocating many objects, leading to a 2% increase in runtime. This was due to unaddressed deprecations in the codebase, which generated excessive warning messages.
What was the outcome of the upgrade process for Shopify?
The upgrade process resulted in a codebase that required cleanup of dead code branches supporting both Rails versions. Shopify utilized a custom Rubocop rule to automate this cleanup after the upgrade was completed.

Key Statistics & Figures

Number of gem dependencies
370
Shopify had to ensure all these gems were compatible with Rails 5 during the upgrade.
Initial number of failing tests on Rails 5
>1000
This number decreased as the team worked to fix issues during the upgrade process.
Percentage of runtime increase due to deprecation warnings
2%
This was noted after the upgrade when running the code that generated numerous warnings.

Technologies & Tools

Some links below are affiliate links. We may earn a commission if you make a purchase.

Key Actionable Insights

1
Eliminate deprecated features as soon as possible to simplify future upgrades.
Waiting to remove deprecated features can lead to a larger codebase, making it more challenging to upgrade in the future.
2
Maintain updated gem dependencies to ease the upgrade process.
Regularly upgrading gems can prevent compatibility issues during major framework upgrades, reducing the overall effort required.
3
Implement a dual CI pipeline to manage compatibility during upgrades.
This approach allows teams to test changes against multiple versions of the framework, ensuring stability and compatibility throughout the upgrade process.

Common Pitfalls

1
Failing to remove deprecated features can complicate future upgrades.
Legacy code that relies on deprecated features can lead to increased technical debt and make it harder to upgrade frameworks as they evolve.
2
Not maintaining gem dependencies can result in compatibility issues.
Outdated gems may not support newer versions of Rails, leading to additional work during an upgrade process.

Related Concepts

Rails Upgrade Strategies
Gem Dependency Management
Continuous Integration Best Practices