13 mins read

Rails 6.1 to 7 Upgrade: Step-by-Step Migration Guide

Planning a Rails 6.1 to 7 upgrade? This guide covers deprecations, Rails compatibility checks, common pitfalls, and real-world upgrade practices.
Blog Image

Raisa Kanagaraj

Technical Content Writer

Blog Image

Upgrading your Rails app isn’t just about swapping version numbers; it’s about future-proofing your codebase while minimizing risk. That’s especially true for a Rails 6.1 to 7 upgrade, which introduces foundational shifts in autoloading, caching, asset handling, and security defaults.

At RailsFactory, we’ve walked dozens of teams through this exact journey. And based on hard-won experience and the collective wisdom from our Ruby on Rails experts, we’ve refined a battle-tested approach that balances speed with stability.

If you’re planning your own Rails 6.1 to 7 upgrade, this guide is your roadmap.

Rails 6.1 to 7 Upgrade: A Step-by-Step, Battle-Tested Approach

A Rails 6.1 to 7 upgrade is best handled as a sequence of steps rather than a single upgrade task. Teams that treat it as a structured process consistently avoid surprises in production and reduce long-term maintenance debt. Below is the same approach we follow while delivering rails upgrade services for large, business-critical applications.

This section also acts as a practical rails upgrade guide you can revisit as you move from planning to deployment.

Step 1: Tackling Deprecation Warnings

Before touching the Rails version itself, the most critical step in a Rails 6.1 to 7 upgrade is addressing all deprecation warnings introduced in Rails 6.1.

Deprecation warnings are Rails’ way of telling you what will break later. Ignoring them means you’ll encounter failures in Rails 7 without clear context, making debugging slower and riskier.

Why this step matters

Deprecations often surface only in edge paths or background jobs

Some warnings are masked by dependencies

Fixing them early keeps your code compatible across versions

This is also where a rails compatibility checker becomes extremely valuable. Tools like RailsUp help surface hidden incompatibilities before runtime errors start showing up.

Key Deprecations You Must Address

Below are some of the most common (and impactful) deprecations teams hit during a Rails 6.1 to 7 upgrade.

ActiveModel::Errors Enumeration Changes

Rails 6.1 changed how errors are stored internally. Treating errors as a hash is deprecated.


# Before 
person.errors.each do |attribute, message| 
end 

# After 
person.errors.each do |error| 
 attribute = error.attribute 
 message = error.message 
end 

Rails 7 will raise an error if the old behavior is used.

URI.parser Removal


# Before 
URI.parser.parse("http://example.com") 

# After 
URI::DEFAULT_PARSER.parse("http://example.com") 

Unsafe Raw SQL

Rails 7 removes support for unsafe raw SQL entirely.


# Before 
User.where("name = '#{name}'") 

# After 
User.where("name = ?", name) 

This change improves security and aligns well with modern Rails practices.

ActiveModel::Errors Mutations

All of these are deprecated:

errors[:base] << "message"

errors[:attribute] = "message"

errors[:base].clear

Use:


errors.add(:base, "message") 
errors.delete(:base) 

Routing Deprecations

Dynamic :controller or :action segments are removed in Rails 7.


# Before 
get ":controller(/:action)" 

# After 
get "users/:action", controller: "users" 

Explicit routing improves security and readability.

Active Job Callback Behavior

Rails 7 changes how after_enqueue and after_perform behave when callbacks halt execution.


# config/initializers/new_framework_defaults_6_1.rb 
config.active_job.skip_after_callbacks_if_terminated = true 

Enable this early to match Rails 7 behavior.

Action Mailer Job Changes

Rails 7 standardizes mail delivery jobs:


# Use MailDeliveryJob instead of DeliveryJob 

Database Configuration Changes

Methods like DatabaseConfig#config are removed. Use:


configuration_hash 

Range#include? Deprecation


# Before 
range.include?(date) 

# After 
range.cover?(date) 

This improves performance and avoids ambiguity.

Step Two: Implementing Dual Boot

Dual booting lets you run Rails 6.1 and 7.0 simultaneously, critical for large applications where a Rails 6.1 to 7 upgrade can't happen in one pull request. Using a rails upgrade tool like next_rails makes this straightforward.

Install the gem and generate your dual boot setup:


# Gemfile 
gem 'next_rails' 

# Terminal 
bundle install 
bundle exec next –init 

This creates Gemfile.next with Rails 7.0 specified. Your CI can now run tests against both versions:


# Rails 6.1 tests 
bundle install 
bundle exec rspec 

# Rails 7.0 tests 
BUNDLE_GEMFILE=Gemfile.next bundle install 
BUNDLE_GEMFILE=Gemfile.next bundle exec rspec 

Fix failures in the Rails 7 build incrementally. Deploy fixes to production running Rails 6.1. They're backwards compatible. Once all tests pass on both versions, the actual Rails 6.1 to 7 upgrade becomes a configuration change rather than a code overhaul.

Step Three: Core Upgrade Execution

With deprecations fixed and dual boot validated, execute the Rails 6.1 to 7 upgrade.

Update Ruby First

Rails 7 requires Ruby 2.7.0 minimum. Ruby 3.0+ is strongly recommended for performance gains and compatibility with modern gems. Update Ruby before Rails as mixing major version changes complicates debugging.

Conservative Bundle Update

Update Rails and immediate dependencies only:


# Gemfile 
gem 'rails', '~> 7.0.0' 

# Terminal - conservative update 
bundle update --conservative rails activesupport actionpack actionview \ 
 activemodel activerecord actionmailer activejob actioncable \ 
 activestorage actionmailbox actiontext railties 

The conservative flag prevents unnecessary gem updates. Your Rails 6.1 to 7 upgrade focuses on Rails changes, not investigating why a random gem broke.

Running rails app:update

Execute bin/rails app:update to generate Rails 7 configuration files. This task prompts for each file conflict. Review carefully because blindly accepting overwrites destroys custom configuration:


bin/rails app:update 

The task generates config/initializers/new_framework_defaults_7_0.rb containing new Rails 7 defaults commented out. Keep config.load_defaults 6.1 initially:


# config/application.rb 
config.load_defaults 6.1 

Uncomment defaults in new_framework_defaults_7_0.rb incrementally. Test after each change. This staged approach catches breaking changes early rather than debugging multiple simultaneous failures.

Mandatory Zeitwerk Migration

Rails 7 removes classic autoloading completely. Applications still using classic mode face immediate failures. Your Rails 6.1 to 7 upgrade requires Zeitwerk compliance.

Zeitwerk enforces strict naming conventions. File user_processor.rb must define UserProcessor and not UserProc, not Processor. Review every file in app/ and lib/:


# app/services/user_processor.rb 
# Wrong - Zeitwerk can't find this 
class UserProc 
end 

# Correct 
class UserProcessor 
end 

Remove require statements for application code. Zeitwerk handles autoloading automatically. Keep require only for standard library and external gems:


# Remove these 
require 'user' 
require 'app/models/user' 

# Keep these 
require 'net/http' 
require 'json' 

Nested modules need matching directory structures:


# app/services/reports/generator.rb 
module Reports 
 class Generator 
 end 
end 

Test Zeitwerk compliance before your Rails 6.1 to 7 upgrade goes to production. Boot the application in all environments. Navigate through features manually because Zeitwerk errors appear in unexpected places.

Critical Breaking Changes Requiring Immediate Attention

Several breaking changes in Rails 7 demand specific handling during your Rails 6.1 to 7 upgrade.

Sprockets No Longer Default

Rails 7 doesn't include sprockets-rails automatically. Applications using the asset pipeline fail with cryptic errors:


Don't know how to build task 'assets:precompile' 

Add Sprockets explicitly:


# Gemfile 
gem 'sprockets-rails' 

Run bundle install and verify asset compilation works locally before deploying your Rails 6.1 to 7 upgrade.

New Cache Serialization Format

Rails 7 introduces cache_format_version = 7.0 for faster, more compact caching. But Rails 6.1 can't read this format. Deploy your Rails 6.1 to 7 upgrade in two phases:

Phase One - Initial Deployment


# config/application.rb 
config.load_defaults 6.1 
config.active_support.cache_format_version = 7.0 

Rails 7 reads both formats. Deploy with this configuration first. Monitor for several days.

Phase Two – Finalization

# config/application.rb 
config.load_defaults 7.0 

Remove new_framework_defaults_7_0.rb entirely. Now your application runs pure Rails 7 defaults.

The key generator digest class shifts from SHA1 to SHA256. Without a rotator, users' sessions invalidate during your Rails 6.1 to 7 upgrade giving them a terrible user experience:


# config/initializers/cookie_rotator.rb 
Rails.application.config.after_initialize do 
 Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| 
   salt_encrypted = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt 
   salt_signed = Rails.application.config.action_dispatch.signed_cookie_salt 

   key_gen = ActiveSupport::KeyGenerator.new( 
     Rails.application.secret_key_base, 
     iterations: 1000, 
     hash_digest_class: OpenSSL::Digest::SHA1 
   ) 

   key_len = ActiveSupport::MessageEncryptor.key_len 
   old_encrypted = key_gen.generate_key(salt_encrypted, key_len) 
   old_signed = key_gen.generate_key(salt_signed) 

   cookies.rotate :encrypted, old_encrypted 
   cookies.rotate :signed, old_signed 
 end 
end 

This rotator allows Rails 7 to read cookies created by Rails 6.1. Remove it 6 months after your Rails 6.1 to 7 upgrade when all old cookies expired.

Active Storage Variant Processor Migration

Rails 7 switches from ImageMagick to libvips for image processing. The performance improvement is significant, but syntax changes break existing transformations:


# ImageMagick syntax (deprecated) 
variant(resize: "100x") 

# libvips syntax (required) 
variant(resize_to_limit: [100, nil]) 

Cropping requires arrays instead of strings:


# Before 
variant(crop: "1920x1080+0+0") 

# After 
variant(crop: [0, 0, 1920, 1080]) 

libvips strictly validates crop boundaries. Negative positions or oversized dimensions throw extract_area: bad extract area errors. Add validation:

def safe_crop(x, y, width, height) 
 x = [x, 0].max 
 y = [y, 0].max 
 width = [width, image.width - x].min 
 height = [height, image.height - y].min 
 [x, y, width, height] 
end 

Active Storage URLs encode transformation parameters. After deploying libvips changes, invalidate cached URLs or users see broken images.

Gem Compatibility and Rails Upgrade Services

Your performance gains after a Rails 6.1 to 7 upgrade depends heavily on gem compatibility. Use a rails compatibility checker early. RailsUp provides instant compatibility reports for your entire Gemfile.

Update gems proactively. Teams maintaining current dependencies find Rails 6.1 to 7 upgrade projects significantly easier. Each gem update is a small, testable change. Upgrading Rails with dozens of outdated gems becomes a massive, risky change.

For gems lacking Rails 7 support, explore alternatives. Unmaintained gems won't receive updates. Forking works as a last resort but adds ongoing maintenance burden. Consider professional rails upgrade services for assistance identifying and replacing problematic dependencies.

Internal gems and engines need updates first. These often get overlooked but block the main application's Rails 6.1 to 7 upgrade. Update internal dependencies before touching the monolith.

Testing Strategy During Rails 6.1 to 7 Upgrade

Test systematically. Start with your automated test suite. You can fix failures methodically rather than randomly. Group related failures together.

Run the application locally. Click through major features. Try edge cases. Automated tests catch logic errors, but manual testing reveals user experience problems your tests miss.

Deploy to staging early in your Rails 6.1 to 7 upgrade process. Don't wait for perfection. Deploy when barely functional, then iterate. Staging exposes integration issues with external services, background jobs, and infrastructure that local development can't replicate.

Coordinate with QA teams. Provide comprehensive testing checklists covering all major features. Fresh perspective catches issues you've become blind to after weeks focused on the upgrade.

Deployment Planning and Production Rollout

Plan your Rails 6.1 to 7 upgrade deployment meticulously. Minimize downtime through careful orchestration.

Consider canary deployments if infrastructure permits. Deploy Rails 7 to a small server percentage first. Monitor error rates, response times, and user experience. Gradually increase rollout percentage if metrics look healthy.

Document rollback procedures explicitly. Test rollback in staging before production deployment. When production deployment fails at 3 AM, clear rollback documentation prevents panic-driven decisions.

Communicate with stakeholders proactively. Give teams advance notice about deployment windows. Your Rails 6.1 to 7 upgrade might cause temporary performance variations or unexpected behavior. Set expectations appropriately.

Post-Upgrade Tasks and Optimization

Your Rails 6.1 to 7 upgrade doesn't end at deployment. Several follow-up tasks remain critical.

Monitor error tracking closely for two weeks minimum. New exception patterns emerge that staging missed. Address these quickly before user impact grows.

Update config.load_defaults to 7.0 after monitoring confirms stability. This finalizes the transition to Rails 7 defaults. Remove new_framework_defaults_7_0.rb.

Address new Rails 7.1 deprecations incrementally. Don't let them accumulate. Fix deprecation warnings as they appear during feature development.

Performance metrics need attention. Rails 7 generally improves performance, but specific applications encounter regressions. Profile carefully using the rails upgrade tool of your choice and optimize where needed.

Common Pitfalls in Rails 6.1 to 7 Upgrade Projects

Zeitwerk configuration causes the most failures. File naming must be exact. Nested modules require matching directory structures. The classic autoloader forgave sloppiness; Zeitwerk doesn't. Use the rails compatibility checker to scan for naming mismatches before deployment.

Gem version conflicts create headaches. Your gem might depend on another gem that doesn't support Rails 7. Sometimes updating through multiple major versions is necessary to reach Rails 7 compatibility. Professional rails upgrade services specialize in navigating these dependency chains.

Test coverage gaps become painfully obvious during a Rails 6.1 to 7 upgrade. Code paths without tests fail silently until production users encounter them. This reinforces why pre-upgrade test coverage matters.

ActiveRecord query changes break subtly. Methods like reorder('').first now behave deterministically. Code relying on non-deterministic ordering needs refactoring to use take explicitly.

Making Future Upgrades Easier

Your Rails 6.1 to 7 upgrade teaches valuable lessons about maintaining Rails applications long-term.

Stay current with patch versions. Update to the latest patch regularly. These updates are low-risk and keep you prepared for major upgrades. A Rails 6.1 to 7 upgrade from 6.1.0 versus 6.1.7 involves significantly different challenges.

Keep dependencies updated through scheduled maintenance sprints. Modern dependency management tools make this easier than manual tracking. Current dependencies make any rails upgrade guide easier to follow.

Fix deprecations immediately. Don't accumulate them. Address deprecation warnings when they first appear. This makes Rails 7.1, or Rails 7.2 to 8.0 upgrades trivial instead of traumatic.

Document your upgrade process thoroughly. Create a team playbook specifically for Rails upgrades. Record what worked, what didn't, and what you'd change next time. This documentation becomes invaluable for future Rails 6.1 to Rails 7 upgrade projects in other applications.

Leveraging Resources and Rails Upgrade Services

Don't upgrade in isolation. The official rails upgrade guide at guides.rubyonrails.org provides comprehensive, authoritative information. Reference it frequently throughout your Rails 6.1 to 7 upgrade.

Community resources offer practical wisdom. Thousands of Rails 6.1 to 7 upgrade projects have been completed. Blog posts, conference talks, and forum discussions provide real-world solutions to common problems.

Professional rails upgrade services exist for teams needing extra support. Companies specializing in Rails upgrades like RailsFactory bring expertise from numerous projects. They've encountered every edge case and can accelerate your Rails 6.1 to 7 upgrade significantly.

Automated rails upgrade tools can streamline the dual boot process. Rails compatibility checker services like RailsUp identify problematic dependencies instantly. Use these tools strategically throughout your upgrade process.

Final Thoughts

A successful Rails 6.1 to 7 upgrade isn’t just about speed; it’s about control. Addressing deprecations early, dual booting strategically, and understanding behavioral changes allows teams to upgrade with confidence.

Whether you’re using an internal Rails pre-upgrade checklist, a rails compatibility checker, or working with expert rails upgrade services, the goal remains the same: a stable, future-ready Rails application that’s easier to maintain and faster to evolve.

The Rails framework continues evolving rapidly. Staying current through regular, systematic upgrades keeps your application maintainable, secure, and positioned to leverage new capabilities.

Your Rails 6.1 to 7 upgrade is one crucial step in an ongoing journey of continuous improvement and technical excellence.

Written by Raisa Kanagaraj

Your one-stop shop for expert RoR services

Join 250+ companies achieving top-notch RoR development without increasing your workforce.

Book a 15-min chat