Anthony Wentzel

Resurrecting a three-year-old legacy Rails app

In 2014 I brought a dormant 2011 Rails 3.1 app back to life. The code was fine. The dependencies were the problem. Notes for any legacy Rails app upgrade.

From 2014 · 2 min read · Published September 2, 2026

In June 2014 I was asked to get an internal dashboard running again. It was a Rails 3.1 app, last touched around December 2011, that tracked engagement metrics for a set of customer products. The code hadn't changed in two and a half years. It no longer started, a classic legacy Rails app problem.

The commit messages from that week are an honest record of how it went. Two of them are "Revert to 1891167 Dec 2011" and "Revert to a3624db... Dec 2011." A few hours later: "omg i got the server up without compass blueprint." Then: "recording steps to get korboard back online."

What had rotted in the legacy Rails app

Nothing in the application code was wrong. Everything around it was:

  • A gem pinned to someone's master branch. The Gemfile pulled grape straight from its git repository with no revision constraint. Three years later, master was a very different library. The fix was to pin a real release:
Gemfile
gem 'rails', '3.1.3'
gem 'mysql2', '~> 0.3.16'
# gem 'grape', :git => 'git://github.com/intridea/grape.git'
gem "grape", "0.2.1"
gem 'coffee-script-source', '~> 1.7.0'
  • Native extensions against a new system. The mysql2 gem had to compile against a much newer MySQL. I spent real time on flags and install_name_tool surgery before discovering a newer patch release of the gem that just worked.
  • An abandoned CSS framework. The app depended on Compass Blueprint, which no longer installed cleanly. Getting the server up without it was the breakthrough, hence the "omg."

Writing it down

The most useful artifact from that week wasn't a fix. It was a setup script with the dead ends left in:

script/setup.sh (excerpt)
brew install mysql
bundle update
bundle install
cp ./config/database.example.yml ./config/database.yml
./script/startup
 
# did not work
# do not attempt these mysql2 fixes:
# rvmsudo ARCHFLAGS="-arch x86_64" gem install mysql2 -- --with-mysql-dir=...

"Do not attempt these" is my favorite comment in that repo. The next person to touch the project, very possibly me, got to skip an afternoon of failed experiments.

Lessons that aged well

  1. Pin to releases, never to a branch. A git dependency without a tag or commit is a time bomb. Lockfiles help, but only if the thing they point to still exists.
  2. The code is rarely what rots. Dependencies, system libraries, and toolchains move on without you. Budget for that when you shelve a project.
  3. Record the dead ends. A setup guide that only lists the steps that worked hides the most expensive information: what not to try.

Related: The React Native AndroidX migration week · The unglamorous WordPress security checklist for a small business site