Actual Code All articles
Careers

Nobody Wants to Hear This: Your Ten-Year-Old Rails App Doesn't Need a Rewrite

Actual Code
Nobody Wants to Hear This: Your Ten-Year-Old Rails App Doesn't Need a Rewrite

Photo: old dusty server basement office London brick walls, via i.pinimg.com

Every developer who inherits an old codebase has had the fantasy. You know the one: we start fresh, pick the modern stack, do it properly this time, and in eighteen months we'll have something beautiful. Meanwhile, the reality of the last decade — the migrations that run on hope, the controller with 900 lines, the model named Misc2 — gets consigned to history.

I want to talk you out of it. Not because the fantasy is wrong about the code — the code probably is a mess — but because it's wrong about nearly everything else.

The Rewrite Graveyard Is Enormous

The industry has known about the second-system problem since the 1970s, and yet rewrites keep failing at a rate that should embarrass us. The pattern is always the same. The new system captures 80% of the old one's behaviour, the remaining 20% turns out to contain all the edge cases that make the business money, and the project drags on while the old system still needs maintaining because you can't switch it off. Eventually someone does the maths, the rewrite is shelved, and you're back where you started — except now you're maintaining two systems.

In UK finance and the public sector, this pattern is compounded by regulation. That gnarled old Rails app might encode years of accumulated compliance logic — FCA reporting quirks, audit trail behaviour, settlement rules nobody documented. A rewrite doesn't just risk bugs; it risks silent bugs, where the system confidently does the wrong thing and nobody notices until an audit or a regulator does.

And here's the career angle, since we're being honest: the developer who proposes the rewrite gets six exciting months and then often moves on. The developer who's left holding both systems inherits the mess. Don't be the person who starts the fire and leaves before the fire brigade arrives.

The Strangler Fig, In Practice

The alternative has a name everyone loves to hate: the strangler fig pattern. Rather than replacing the system, you gradually grow a new one around it until the old core has nothing left to do.

Concretely, for a monolithic Rails app, it looks like this:

  1. Put a routing layer in front. Nginx, a reverse proxy, or a lightweight API gateway sits in front of the monolith. Nothing changes for users, but now you control which requests go where.

  2. Pick a seam and extract. Choose one bounded piece of functionality — say, generating customer statements — and build it as a new service or module. Route traffic for it through the proxy. Crucially, write the new version against a proper contract test suite so you know it behaves like the old one.

  3. Mirror, then cut over. For anything risky, run both implementations and compare outputs before sending real traffic to the new code. Shadow traffic is your friend.

  4. Delete ruthlessly. Once a piece is migrated, the corresponding old code dies. This is the step teams skip, and it's why rewrites-by-another-name balloon: if you never delete, you're not strangling, you're hoarding.

The beauty of this approach is that it's reversible. If a migration goes badly, you flip the route back. Try doing that with a big-bang cutover on a Friday night.

Getting the Budget Holders to Say Yes

Here's the part most technical write-ups skip: nobody outside engineering approves a refactor. Finance directors don't fund "technical debt reduction" — they fund reduced incident costs, faster feature delivery, and lower staff churn.

So translate. That Rails 5 app you can't upgrade? In the board pack, that's "our core platform no longer receives security patches, exposing us to breach and compliance risk." The two-week effort to add automated tests around the payments flow? "We can currently only change our payment system during weekend outages; this removes that constraint."

Two tactics that consistently work with UK stakeholders:

Ship Improvements While the Thing Is Still Earning

The final mental shift: modernisation isn't a project with an end date, it's a tax you pay continuously. Every ticket is a chance to improve. Touching a legacy controller? Extract one method into a service object with tests. Upgrading a dependency for a security patch? Do the next minor Rails version while you're in there. Adding an endpoint? Write it in the new style, in the new structure, even if it lives inside the monolith for now.

This is how ageing systems in British retail and government actually get fixed — not by heroic rewrites but by hundreds of small, boring, reversible improvements made by developers who understood that the old code was still paying the bills.

The basement Rails app isn't going anywhere, and honestly, that's fine. It's survived longer than most startups and most rewrites. Treat it with a bit of respect, strangle it slowly, and it might just outlast your tenure — which, in this line of work, is the real mark of success.

All Articles

Related Articles

Nobody Has Time for TDD, So Here's the Version That Fits in Your Commute

Nobody Has Time for TDD, So Here's the Version That Fits in Your Commute

The Great Rebalancing: Where UK Dev Pay and Remote Work Landed After the Dust Settled

The Great Rebalancing: Where UK Dev Pay and Remote Work Landed After the Dust Settled

Postman Returns 200, Production Returns Chaos: Closing the Gap in Your API Testing

Postman Returns 200, Production Returns Chaos: Closing the Gap in Your API Testing