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.
Cookie Rotator for Session Preservation
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.