The Friday Deploy

The plain English newsletter for people who run the business, not the tech stack. No jargon. Every Friday.

What Breaks When You Upgrade Rails (And Why)

December 12, 2025

Your developer just told you the Rails upgrade will take eight weeks and cost $32,000. You’re running Rails 5.2. Rails 8 is current. The upgrade seems like it should be straightforward. It’s the same framework, just a newer version.

“Why does it take two months to update software?” you ask. “Can’t you just change the version number and run some updates?”

Here’s the truth: you’re not paying $32,000 for a Rails upgrade. You’re paying $32,000 for three years of deferred maintenance. The application has been running fine, so nobody touched it. What could possibly go wrong?

Everything, as it turns out.

This is the conversation that happens in businesses running Rails applications when upgrades become unavoidable. The timeline and cost seem excessive for what sounds like routine maintenance. But Rails upgrades are rarely routine when you’ve let the application fall years behind, and understanding why helps you budget appropriately, set realistic expectations, and more importantly, avoid repeating this expensive mistake.

Why Rails Upgrades Break Things

Rails follows a versioning system where major and minor versions can introduce breaking changes to the public API. That means code that worked perfectly in Rails 5.2 might not work at all in Rails 6.0, even though it’s the “same” framework.

These aren’t bugs or mistakes. They’re deliberate improvements where the Rails team decided the benefits of changing how something works outweigh the pain of breaking existing applications. Deprecated features get removed. Default behaviours change. Configuration requirements shift. New approaches replace old patterns.

For simple applications with minimal customisation, upgrades might be quick. But most production Rails applications have accumulated years of code, custom gems, third-party integrations, and dependencies that all need to work together. Changing one piece creates a cascade of adjustments throughout the system.

The Rails 5.2 to Rails 8 path involves multiple major version jumps (5.2 → 6.0 → 6.1 → 7.0 → 7.1 → 7.2 → 8.0). Each transition introduces breaking changes. Skipping versions is technically possible but practically dangerous because you miss deprecation warnings and encounter multiple breaking changes simultaneously.

The Typical Breaking Changes

While every Rails upgrade is different depending on your specific codebase, certain patterns emerge consistently:

Deprecated features removed. Rails warns about features that will be removed in future versions through deprecation notices. These warnings appear in logs and test output. If your team ignored those warnings (common when deadlines are tight), the upgrade removes those features entirely and your application breaks. Code that relied on the deprecated functionality needs rewriting.

Configuration changes. Each Rails version changes how the framework is configured. New security defaults get introduced. Database connection handling changes. Asset pipeline options evolve. The rails app:update command generates new configuration files, but you need to manually review and integrate them with your existing customisations without breaking functionality.

Gem compatibility. Your Rails application likely uses dozens of gems (third-party libraries). Not all gems update immediately when new Rails versions release. Some gems become abandoned and never update. During an upgrade, you’ll discover which gems are incompatible with the new Rails version and need to find replacements, update to newer gem versions, or wait for gem maintainers to release compatible versions.

Test suite failures. Rails upgrades often change testing behaviour. Tests that passed before the upgrade fail afterward, not because your code broke, but because Rails changed how tests run or what defaults they use. Every failing test needs investigation to determine whether it’s revealing a real problem or just needs updating to match new Rails conventions.

Autoloading changes (Zeitwerk). Rails 6 introduced a new code loading system called Zeitwerk that replaced the old autoloading mechanism. This affects how files are named, where they’re located, and how classes are loaded. Applications with non-standard file naming or loading patterns need refactoring to work with Zeitwerk.

JavaScript and asset pipeline changes. The way Rails handles JavaScript, CSS, and other assets has evolved dramatically. Rails moved from Sprockets to Webpacker, then to jsbundling-rails and cssbundling-rails, and most recently to Importmap. If your application uses an older approach, you might need to migrate your entire frontend asset handling during the upgrade.

Why You Can’t Just Skip Versions

The temptation is obvious: “If Rails 5.2 to 6.0 is painful, and 6.0 to 6.1 is painful, why not jump directly from 5.2 to 8.0 and only do the pain once?”

This approach almost always fails for larger applications. Here’s why:

Deprecation warnings in Rails 5.2 tell you what will break in Rails 6.0. If you skip to Rails 8.0, you miss three major versions of deprecation warnings. Features that were deprecated in Rails 6 and removed in Rails 7 will just break without warning when you try to run Rails 8.

Error messages become ambiguous. When something breaks after jumping three versions, is it because of a Rails 6 change, a Rails 7 change, or a Rails 8 change? You’ll spend hours debugging issues that would have been obvious with incremental upgrades.

Gem compatibility becomes nearly impossible. Finding gems that work with both Rails 5.2 and Rails 8.0 is harder than finding gems compatible with adjacent versions. You’re essentially trying to update everything simultaneously rather than incrementally.

The Rails team designs the upgrade path to work incrementally. Following that path is almost always faster and safer than trying to outsmart it by jumping versions.

What “Eight Weeks” Actually Means

When your developer estimates eight weeks for a Rails upgrade, they’re not working on it full-time for eight weeks. The timeline typically breaks down like this:

Week 1-2: Preparation and assessment. Review current Rails version and all dependencies. Identify deprecated features being used. Check gem compatibility with target Rails version. Set up a separate upgrade branch. Update development and staging environments.

Week 3-4: First version increment (e.g., 5.2 to 6.0). Update Rails version in Gemfile. Update incompatible gems. Run rails app:update and integrate configuration changes. Fix failing tests. Address deprecation warnings. Test application functionality manually.

Week 5-6: Second version increment (e.g., 6.0 to 6.1). Repeat the process for the next version. Fix new breaking changes. Update more gems if necessary. More testing and bug fixing.

Week 7-8: Final increment and deployment. Complete remaining version jumps. Comprehensive testing across all features. Performance testing to ensure no regressions. Deployment planning and execution. Monitor production for issues.

Much of this time isn’t active coding. It’s testing, debugging, researching gem compatibility issues, and waiting for test suites to run. For an application with good test coverage, running the full test suite might take 30-60 minutes. Running it multiple times per day while debugging adds up quickly.

The Hidden Costs That Extend Timelines

Several factors commonly extend Rails upgrades beyond initial estimates:

Low test coverage. If your application lacks comprehensive tests, developers can’t confidently determine what the upgrade broke. Manual testing every feature for every version increment multiplies timeline significantly. Applications with less than 60% test coverage often take twice as long to upgrade.

Abandoned gems. Finding a gem that’s been abandoned and has no Rails 6+ compatible version forces a decision: fork the gem and maintain it yourself (expensive), find an alternative gem and refactor code to use it (time-consuming), or rewrite the functionality entirely (very time-consuming).

Custom modifications to Rails internals. Some applications patch or monkey-patch Rails core behaviour. These modifications almost always break during upgrades because they depend on Rails internal implementation details that change between versions. Removing these patches and finding proper solutions extends timelines significantly.

Production issues discovered post-upgrade. Even with thorough testing, production environments sometimes reveal issues that staging didn’t catch due to scale, specific data patterns, or external integrations. Budget time for post-deployment fixes.

Multiple Ruby version upgrades. Rails versions often require specific Ruby versions. Rails 6.1 requires Ruby 2.5+. Rails 7 requires Ruby 2.7+. Rails 8 requires Ruby 3.1+. If you’re also upgrading Ruby (likely), that’s additional complexity and testing.

What You Should Ask Your Developer

To assess whether the proposed timeline and cost are reasonable, ask these questions:

What’s the upgrade path? Which specific Rails versions will you increment through (5.2 → 6.0 → 6.1 → 7.0, etc.)? Knowing the path helps you understand the scope.

Which gems are incompatible? Have you identified all gems that need updating or replacing? How many are there? This is usually discoverable early in the process.

What’s the test coverage? If test coverage is low, acknowledge that manual testing will extend timelines. Consider writing additional tests before upgrading if possible.

What’s the biggest risk? What specific part of the application is most likely to break or cause delays? This helps you understand where problems might emerge.

What’s the rollback plan? If the upgrade goes to production and causes critical issues, how quickly can you revert? Having a clear rollback plan reduces risk.

Is this incremental or all-at-once? Can parts of the upgrade be deployed separately, or is this one big deployment at the end? Incremental approaches reduce risk but may extend timeline.

The Cost of Delaying Upgrades

Some businesses react to upgrade timelines by postponing indefinitely. “Eight weeks and $32,000? Let’s wait until next year when we have more budget.”

This approach accumulates risk. Here’s what happens when you delay:

Security vulnerabilities. Unsupported Rails versions don’t receive security patches. Rails 5.2 reached end-of-life in June 2022. Running it in 2025 means known security vulnerabilities exist that will never be patched. This creates compliance risks and actual breach risks.

Upgrade cost compounds. Waiting two years doesn’t reduce upgrade cost. It increases it. More versions to jump. More breaking changes accumulated. More gems abandoned. More custom code built on deprecated features. The upgrade becomes harder and more expensive the longer you wait.

Gem ecosystem moves on. New gems and tools assume recent Rails versions. Older Rails versions get left behind. Your ability to integrate new services or adopt new approaches degrades over time.

Recruitment and retention problems. Developers prefer working with current technology. Applications stuck on Rails 5.2 in 2025 signal technical neglect. This makes hiring harder and increases developer turnover as talented engineers leave for projects using modern tools.

Performance and feature improvements missed. Each Rails version includes performance optimisations and new features. Staying on old versions means your application runs slower and requires more custom code for features now built into the framework.

Alternatives to Full Upgrades

If the full upgrade timeline is genuinely impossible for business reasons, consider these alternatives:

Partial upgrades. Upgrade to the next version only, not all the way to current. Rails 5.2 to 6.0 is less work than 5.2 to 8.0. This reduces immediate timeline but commits you to upgrading again later.

Security-only backports. Some services (like HeroDevs’ Never-Ending Support) provide security patches for unsupported Rails versions, buying time to plan proper upgrades. This is expensive ongoing cost but might be cheaper than emergency upgrades.

Feature freeze during upgrade. Stop all feature development for the upgrade period. This reduces conflicts and complications but has obvious business implications.

Staged rollout. Upgrade staging first, run both versions in parallel for a period, then upgrade production. This catches production-specific issues earlier but requires maintaining two environments.

None of these eliminate the need to upgrade eventually. They just adjust timing and risk distribution.

How to Avoid This Entire Problem

Here’s the frustrating part: all of this pain is avoidable.

If you’d upgraded Rails 5.2 to 6.0 when Rails 6.0 was released, it would have taken two weeks and cost maybe $6,000. Then 6.0 to 6.1 another two weeks. Then 6.1 to 7.0 another two weeks. Each increment is manageable because you’re only dealing with one version’s worth of breaking changes at a time.

Instead, you waited three years. Now you’re facing eight weeks and $32,000 to jump through six versions simultaneously. The total cost hasn’t reduced. It’s multiplied.

The problem isn’t that Rails upgrades are expensive. The problem is letting your application fall three years behind.

Businesses that stay current spend less money on upgrades over time. They spend it in smaller, predictable increments instead of large crisis interventions. More importantly, they never face the security risks, recruitment problems, or emergency situations that come with running unsupported software.

The right approach is simple: upgrade Rails within 6-12 months of each new version release. When Rails 7.0 comes out, upgrade from 6.1 to 7.0 before Rails 7.1 releases. This keeps you perpetually one version behind current at most, which is perfectly fine.

Each upgrade takes 1-2 weeks instead of 8 weeks. Each costs $5,000-$8,000 instead of $32,000. You do it more frequently, but the total annual cost is lower and the risk is dramatically reduced.

Regular small upgrades cost less than periodic large ones.

This is true for Rails, Ruby, operating systems, and every other piece of technology infrastructure you run.

If you’re facing a massive upgrade right now, learn from it. Don’t let this happen again. After you complete this upgrade, commit to staying current going forward. Budget for small annual upgrades as regular maintenance, not crisis interventions every few years.

The most effective way to stay current is a monthly service retainer with your developer or agency.

A modest retainer ($2,000-$5,000 monthly) ensures someone is consistently monitoring your application, addressing deprecation warnings as they appear, and performing incremental upgrades before they become emergencies. This ongoing relationship costs far less annually than periodic crisis interventions and provides continuous maintenance rather than neglect followed by panic.

With a retainer in place, Rails upgrades happen when convenient for your business, not when security vulnerabilities force your hand. Deprecation warnings get fixed immediately rather than accumulating for years. Gem updates happen regularly. Your application stays healthy rather than degrading slowly until it requires expensive emergency intervention.

The eight-week, $32,000 upgrade you’re facing is the cost of neglect, not the cost of Rails maintenance. Rails maintenance, done properly through regular attention (whether internal resources or external retainer), costs a fraction of that and causes far less disruption.

Making the Decision

Rails upgrades aren’t optional for long-term application health. The question isn’t whether to upgrade but when and how.

An eight-week, $32,000 upgrade for a production Rails application is reasonable if:

  • The application is 3+ versions behind
  • It has moderate complexity with dozens of gems and custom features
  • Test coverage is decent (60%+)
  • The timeline includes testing, not just coding

That same upgrade should raise concerns if:

  • The application is relatively simple with few dependencies
  • Test coverage is very high (90%+)
  • The upgrade path is short (one or two versions)

Trust your developer’s assessment if they can clearly articulate the upgrade path, identify specific compatibility issues, and explain the biggest risks. Be sceptical if the estimate seems to be pulled from thin air without analysis.

Budget for 20-30% contingency over the initial estimate. Unexpected issues are normal in upgrades. Finding an abandoned gem with no replacement or discovering a critical production-only bug adds time and cost.

The Bottom Line

Rails upgrades break things by design. The framework evolves, and evolution means change. Your application needs to change with it.

Eight weeks and $32,000 might feel expensive for “just updating software,” but you’re not paying for the upgrade. You’re paying for years of deferred maintenance. If you’d kept current, you’d have spent less money overall and avoided this situation entirely.

The real lesson: don’t let this happen again. After completing this upgrade, commit to staying current. Budget for Rails upgrades as recurring annual maintenance (1-2 weeks, $5,000-$8,000 per year) rather than crisis interventions every few years (8+ weeks, $30,000+).

Regular small upgrades cost less than periodic large ones. They’re less risky, less disruptive, and keep your application secure and maintainable.

Your Rails application needs maintenance just like any other business infrastructure. The question is whether you pay for it in small predictable amounts annually, or in large painful amounts every few years when you have no choice.

Stay current. It’s cheaper and far less painful than the alternative you’re experiencing right now.

Read more Technical Deep Dives

Breaking Changes, Maintenance, Rails, Technical Debt, Upgrades

Previous Next

The Friday Deploy

The plain English newsletter for people who run the business, not the tech stack. No jargon. Every Friday.