Why one minor version at a time
The Rails upgrade guide tells you to move slowly, one minor version at a time, so that deprecation warnings point out what to fix before the next step. The loop it describes is: get the tests passing, move to the newest patch release of your current minor, fix what fails and what is deprecated, then move to the latest patch of the next minor and repeat. A single jump over three minors puts three sets of changes into one failing run, and nothing tells you which one is responsible.
- Record the test result after each step, not only at the end.
- Take the newest patch release of the current minor before moving on.
- Upgrade Ruby separately from Rails, to the latest Ruby your current Rails minor supports. The guide gives only minimum Rubies, and a published compatibility table recommends an older Ruby for Rails 7.0 than for 7.1 and later, so raise Ruby again as each Rails minor allows.
What the guide lists for each step
For 7.0 to 7.1 the guide names, among other things, a renamed key file used in development and test that invalidates sessions there if the old key is not carried over, a new cache serialisation format with a staged rollout advised, autoload paths no longer on the load path, and connection pooling by default for Memcache and Redis cache stores. For 7.1 to 7.2 it notes that tests now honour a configured Active Job queue adapter and that alias_attribute changed. For 8.0 to 8.1 it notes that schema.rb columns are sorted alphabetically by default, so a diff of the schema file can change without a database change. For 7.2 to 8.0 the guide only points to the release notes, so read those.
- A changed queue adapter in tests can reveal jobs that never ran in the suite.
- A sorted schema file is not evidence of a changed table.
Adopt new defaults one at a time
The update task is interactive: review each file diff before accepting it. It also generates a file of new framework defaults for the target version. Your app keeps its old behaviour until you enable each new default, and once all are enabled you delete that file and change the load-defaults setting, which applies the defaults of the chosen version and every earlier one. Enabling them one by one, with the suite run after each, shows which default affects which behaviour.
- Do not accept the whole generated file without reading it.
- List any default left off, with the reason, so the next upgrade does not rediscover it.
A safe first investigation, and what does not fit
Before you change anything, record the Rails and Ruby versions, run the test suite on a copy and note what fails today. That is read-only and needs no secrets. This approach assumes the app is already on a 7.x release with a runnable suite. A Rails 6 app has an earlier decision to make about autoloading, and an app that still builds JavaScript with Webpacker has a build decision to make; both come before the version steps.
- Never copy the production secret key or database into a test copy to see whether an upgrade works.
- Gems without a release for the target Rails version are a stop condition, not a detail.
How the fixed job is accepted
The Rails 7 to 8.1 job is accepted on evidence: the app installs and boots on the agreed final Ruby, every minor step has its own recorded test run and deprecation list naming the Ruby and Rails versions it ran on, up to five named flows complete on staging, and the release plan says whether the cache format change affects you, with reverse steps rehearsed. Payment follows those checks and your sign-off; the starting price is an untested proposal. Send the versions and the flows that matter, not code or keys.
Sources and limits
- Rails guides: upgrading Ruby on Rails Checked 2026-10-11.
- The guide recommends moving one minor version at a time, starting from passing tests, and upgrading Ruby separately before Rails, to the latest Ruby you can; it gives only minimum Ruby versions per series (2.7.0 for 7.0 and 7.1, 3.1.0 for 7.2, 3.2.0 for 8.0 and 8.1).
- The update task creates a new_framework_defaults file; the app keeps its old defaults until each new default is enabled, after which the file is removed and the load-defaults setting changed.
- For 7.0 to 7.1 it lists, among others: renamed dev/test secret key file, a new cache serialization format with staged rollout advised, autoload paths no longer on the load path, and connection pooling by default for Memcache and Redis cache stores.
- For 7.1 to 7.2 it lists that tests honour a configured Active Job queue adapter and that alias_attribute changed; for 8.0 to 8.1 it lists alphabetically sorted columns in schema.rb.
- Rails guides: configuring Rails applications Checked 2026-10-11.
- Setting load_defaults for a version applies that version's defaults and those of all earlier versions.
- FastRuby: Rails and Ruby compatibility table Checked 2026-10-11.
- The table, updated 30 September 2026, recommends Ruby 3.3 for Rails 7.0.Z and Ruby 3.4 for 7.1.Z, 7.2.Z, 8.0.Z and 8.1.Z.