The New Default. Your hub for building smart, fast, and sustainable AI software

See now
Old Ruby Codebase – When to Update, What to Consider (Checklist)

Old Ruby Codebase – When to Update, What to Consider (Checklist)

Jan Dudulski
|   Updated May 29, 2026

A programming saying to live by: "code that you don't touch gets rusty over time." Software is not a completely isolated, independent unit – even when using containerization like Docker – but something that lives in a continuously evolving ecosystem.

The platform where you ran the first version of your system is probably not the same one running it today.

To make things more complicated, we rarely build everything from scratch. Instead, we rely on dependencies – hats off to the underappreciated community of open source – which rely on dependencies, which rely on dependencies, which end up with a huge matrix of version constraints.

If you neglect regular maintenance, you can wake up one day forced to make a huge change because you can't add a new feature, can't ship a bug fix, or in the worst case, can no longer run the application at all.

Executive Summary

Regular dependency updates are the single most effective risk-reduction practice for any Ruby codebase. The business case is straightforward: security vulnerabilities in outdated dependencies are a direct path to data breaches, and those breaches are expensive. If you're already behind on updates, the answer isn't a big-bang overhaul – it's one version at a time, with continuous testing, while keeping feature work running in parallel. This post covers when it's time to update, your options, and what to prioritize when you're short on time.

How to Know It's Time to Update?

First, to Understand: What

There's an old maxim: "The best code is no code at all." Every line of code you write is already legacy code that may contain bugs and require maintenance. There's always a risk that a line working today will stop working tomorrow.

That's why we write automated tests and run them as often as possible.

This catches regressions and unexpected problems related to environmental changes, as well as known security issues (I've seen dozens of applications with Gemfile fixed on forked versions or simply not updated gems since initial installation).

And breaking changes in newer versions of dependencies.

And how does that affect the business?

Running on an outdated legacy system creates real business risk – it can slow down new feature development, make it harder to onboard new team members, trigger a breakdown, or create a foundation for security leaks.

According to the IBM Cost of a Data Breach Report 2025, the global average cost of a data breach is now $4.44 million, with organizations taking an average of 241 days to identify and contain a breach.

The per-record cost in the 2024 edition was $173. Healthcare, financials, pharmaceuticals, technology, and energy see the most costly breaches – exactly the industries where Ruby on Rails applications are common.

This is not abstract risk: an outdated gem with a known vulnerability is a direct path into that statistic.

Ok, We'll Update. What Are The Options?

The easiest approach is usually the best one – make regular updates and test your codebase in an environment as close to production as possible.

Regular updates are like brushing your teeth twice a day and visiting the dentist every six months – they don't cause much pain and can help you enjoy a beautiful smile into old age. It doesn't guarantee you'll have no problems, but it reduces risk to a bare minimum.

If you only visit the dentist when pain arrives, you can quickly lose all your teeth.

We're fortunate to live in an era when most of this job can be done automatically.

Tools like Dependabot or Renovate can check what needs updating and prepare pull requests with the changes – it's mostly a matter of goodwill and setting them up.

What if my codebase is already out of date?

If you're learning your lesson from an already outdated legacy codebase, there's no need to panic.

But beware of jumping into deep water and trying to improve everything in a single step. That's a straight path to a broken application with infinite hidden traps waiting for you.

What I'd suggest instead: make the smallest possible step forward. Update one thing by one version, verify everything works, and repeat. Don't stop working on new features in the meantime – updating itself can be a long process.

If there are backward-incompatible changes, adjust your codebase first (and break that work into multiple tasks if needed), verify it works, then make the update. Learning about refactoring patterns can also help improve a legacy codebase generally.

A clean codebase with clean architecture, among many other benefits, also minimizes the cost of upgrades, dependency swaps, or even replacing entire application modules – whether rewritten from scratch or replaced with a third-party solution.

If I don't have time, what should I prioritize?

The riskiest decision you can make is to postpone security-related updates.

Security updates are easy to ignore with the false belief "it won't happen to me." That's a real Russian roulette that can kill the business, and the $4.44M average breach cost from IBM's research is the kind of thing that makes that concrete.

Next in line are updates that fix annoying bugs or actively block your development. Last are purely regular updates – the "brushing your teeth" work. It's not a problem to skip it from time to time, but don't make it a bad habit.

Don't Panic and Update: Legacy Codebase Update Checklist

  • Assess what needs to be updated

  • Break down updates into tasks – the smaller the better

  • Create a realistic plan with focus and milestones – it's not possible to update and test "everything" in one sprint

  • Prioritize as: security-related updates, blockers, and regular updates

  • Don't neglect new features and maintenance – updating itself is a long process

  • Perform updates one version at a time, verifying everything works after each step

  • Handle backward-incompatible changes with care – adjust your codebase first

  • Take the opportunity to improve processes for next time: why was the update necessary? Which risks could have been minimized? Is test coverage sufficient?

Working With a Legacy Ruby Codebase at Scale

Updating a Ruby codebase in isolation is one challenge. Doing it while a product is actively growing – adding engineers, shipping features, and scaling infrastructure – is another.

Monterail's partnership with Seat Unique is a practical example.

The platform has been built and maintained on Ruby on Rails since 2018, evolving through multiple architectural upgrades, including a full frontend migration to Next.js and infrastructure move to AWS – all while the product grew 7,900%+ in revenue over four years and raised £14.5M in 2025.

Maintaining a healthy, updatable codebase was foundational to that growth: a codebase that can't be updated can't be extended, and a codebase that can't be extended can't scale.

If you're dealing with a legacy Ruby codebase and need to scope a modernization plan alongside active product work, Monterail's Ruby on Rails team has navigated this pattern across many long-term partnerships.

Key Takeaways

  • Regular dependency updates are the single most effective maintenance practice. Like brushing your teeth: skip it occasionally and nothing happens; make it a habit to skip and the damage compounds.

  • The IBM Cost of a Data Breach Report 2025 puts the global average breach cost at $4.44M and time to identify and contain at 241 days. Outdated dependencies with known security vulnerabilities are a direct path into that statistic.

  • If you're already behind, update one version at a time. Don't try to fix everything at once – that's a recipe for a broken application with cascading hidden failures.

  • Security updates come first, then blockers, then regular updates. Never postpone the first category.

  • A clean codebase with clear architecture minimizes future upgrade costs. Every time you take on technical debt, you're borrowing against your future ability to update and extend the system.

Why Wait for a Crash When Preventive Maintenance Can Save Your App?

Regular updates are how you maintain a healthy application. Underestimating this can hit a business in many unexpected ways. Prevention is better than a cure.

If you've already neglected this part of development, don't panic. Introduce a repair plan with slow but continuous improvement, and you can work your way out of it.

ror codebase faq

Jan Dudulski avatar
Jan Dudulski
former Engineering Leader
Linkedin
Jan had spent over 10 years of his career at Monterail, starting as Ruby on Rails Developer and reaching the position of Principal Engineer. After leaving Monterail, he went on to become Principal Software Engineer at Gainsight.