A Rails app that hasn’t been maintained in two years looks free. Nothing is being spent on it, it’s still serving customers, and the money that would have gone to a developer went somewhere more visible instead. Then a payment integration deprecates its API, or a gem CVE lands, or the one person who knew how deploys work stops answering email, and the invoice for those two quiet years arrives all at once.

We spend a lot of our time taking over Rails apps in exactly this state, so we’ve seen what the deferral actually costs. It’s worth putting numbers and mechanisms on it, because “technical debt” as a phrase has lost all persuasive power with the people who set budgets.

Where the cost accrues

Security exposure. Ruby versions reach end-of-life every spring, and once yours does, there are no more security patches for the language your business runs on. Gems accumulate published CVEs with public proof-of-concept exploits. None of this announces itself; your app runs exactly as well the day after a CVE is published as the day before. The cost is a growing probability of a very bad week, and unlike most costs on this list, its ceiling is “breach disclosure letter.”

Feature velocity decay. Every library you’re pinned to constrains every other one. On an app several majors behind, adding a payment provider or a reporting feature starts with archaeology: which gem versions still work here, which documentation still applies, which Stack Overflow answers are from the right decade. Features that should take a week take three, and the extra two weeks get quietly priced into every estimate as long as the app stays old.

Hiring drag. Good Rails developers can work anywhere, and they will choose codebases where their knowledge applies. A Rails 5 app on Ruby 2.6 with no test suite filters your candidate pool down to people desperate enough to accept it, which is a rough hiring filter to run on purpose. Contractors quote higher for old stacks for the same reason, when they quote at all.

The rescue premium. This is the one we can quote directly, because rescue work is a service we sell. When maintenance is continuous, an upgrade is a scheduled, boring line item. When it’s deferred until something forces it (a deprecation deadline, an outage, an acquirer’s due diligence), the same underlying work costs a multiple: it’s urgent, it’s tangled together (the Rails upgrade needs the Ruby upgrade needs six gem replacements), and it has to happen while the app is misbehaving in production. Compressing three years of skipped maintenance into two months is dramatically more expensive than doing it as you go, on top of whatever the triggering incident cost.

The rewrite trap

At this point someone, often a prospective agency, proposes rewriting the whole thing. We’ve been brought in after proposals like that, and our position is the same one we publish on our services pages: a full rewrite is usually the wrong call. Old code that has been serving customers for years encodes thousands of small correct decisions that nobody remembers making. A rewrite discards them all and rediscovers them in production, one incident at a time, while the business pays for two systems.

The unglamorous alternative works: audit what exists, stabilize it, upgrade it in steps, and keep it maintained. Rails makes this genuinely tractable. The framework’s upgrade path is documented and stepwise, and an app that gets a steady hour of care per week almost never ends up in the rescue category.

What continuous maintenance looks like

For the apps we run, maintenance is a monthly retainer, and the first month follows the fixed sequence described on our takeover engagements page. After that it’s steady-state: dependency updates and Rails upgrades on schedule, security patches before they’re your problem, tests around everything we touch (we target 80-90% coverage), and a weekly summary in a shared Slack channel so nobody wonders what happened to the bug report.

Our longest-running proof is Wine Spies, an e-commerce wine retailer we’ve partnered with since 2016. That application has grown revenue 850% in that span, on Rails, without a rewrite. The app never became a rescue project because it never got the chance to decay into one.

Deciding what your app needs

A useful self-assessment takes five minutes: What Ruby and Rails versions are you on, and are they still receiving security patches? When did dependencies last get updated? Could someone other than your current developer deploy tomorrow? If the answers make you wince, you already have a maintenance bill. It grows whether or not you pay it.

An audit tells you exactly how big it is. That’s a fixed, small piece of work with a concrete deliverable, and it converts a vague sense of dread into a prioritized list. We wrote up what a week-one audit typically finds if you want to know what to expect before commissioning one.