6 mins read

How to Upgrade from Rails 8 to Rails 8.1 - A Practical Guide

Preparing for a Rails 8.1 upgrade? Follow this structured guide to avoid breaking changes and ensure stability.
Blog Image

Raisa Kanagaraj

Technical Content Writer

Blog Image

Upgrading your Rails application might feel like routine maintenance, but each minor version, like the jump from Rails 8 to Rails 8.1, can introduce subtle changes that impact stability, performance, or even basic functionality. If you’re planning a Rails 8.1 upgrade, you’re in the right place. This guide walks you through the essential steps to make the transition smooth, predictable, and low-risk.

Unlike major version upgrades like Rails 6 to 7, moving from Rails 8 to 8.1 doesn’t overhaul your entire stack. But it does enforce stricter conventions, remove deprecated patterns, and refine internal behaviors. Skipping preparation can lead to silent bugs or broken features in production. So let’s get your app ready.

Step 1: Tackle Deprecation Warnings First

The first and most important step in a Rails 8.1 upgrade is resolving all deprecation warnings introduced in Rails 8.0. These warnings are your roadmap. Each one points to code that will either change behavior or stop working in Rails 8.1.

Deprecation warnings can appear in logs, during test runs, or through monitoring tools. Some may only show up in less frequently used code paths, which is why reviewing the full list of known deprecations is critical.

Routing Deprecations

Dynamic routing patterns are being phased out in favor of explicit, predictable routes.

Dynamic action segments are deprecated

Instead of allowing Rails to infer actions dynamically, define them explicitly.


# Before 
get 'ui(/:action)', controller: 'ui' 

# After 
%w[index edit show].each do |action| 
 get "ui/#{action}", action: action, controller: 'ui' 
end 

Dynamic controller segments are deprecated

Routes that dynamically resolve controllers should be replaced with explicit mappings.


# Before 
get ':controller(/:action(/:id))' 

# After 
get 'users/:action(/:id)', controller: 'users' 

These changes improve clarity and align your routes with future Rails behavior.

Query String and Parameter Parsing Changes

Rails 8.1 tightens how query strings and parameters are parsed.

Semicolons as query separators are deprecated


# Before 
http://example.com/search?query=rails;sort=asc 

# After 
http://example.com/search?query=rails&sort=asc 

Leading brackets in parameter names are deprecated


# Before 
params['[user]'] 

# After 
params['user'] 

Both changes prevent ambiguous parsing and unexpected behavior.

Active Storage and Time Handling Updates

AzureStorageService is deprecated

Rails no longer maintains this service directly.


# Before 
ActiveStorage::Service::AzureStorageService.new(...) 

# After 
require 'azure/storage/blob' 
Azure::Storage::Blob::BlobService.create(...) 

Make sure to update your Gemfile and test thoroughly, as this gem is maintained outside the Rails core team.

Time zone preservation changes

Rails 8.1 preserves the full timezone instead of just the offset.


# config/application.rb 
config.active_support.to_time_preserves_timezone = :zone 

Enabling this early helps you catch timezone-related issues before the final upgrade.

Active Record and Background Job Deprecations

ActiveRecord::Base.connection is deprecated


# Before 
ActiveRecord::Base.connection.execute("SELECT * FROM users") 

# After 
ActiveRecord::Base.connection_pool.with_connection do |conn| 
 conn.execute("SELECT * FROM users") 
end 

Active Job enqueue configuration changes

Symbol-based settings are deprecated in favor of booleans.


# Before 
MyJob.enqueue_after_transaction_commit = :always 

# After 
MyJob.enqueue_after_transaction_commit = true 

Global configuration is also deprecated. Each job should now manage its own enqueue behavior.

sucker_punch adapter is deprecated


# Before 
config.active_job.queue_adapter = :sucker_punch 

# After 
config.active_job.queue_adapter = :async 

These updates make job behavior more predictable and explicit.

Step 2: Set Up Dual Booting

Once deprecations are handled, implement dual booting. This lets your app run on both Rails 8.0 and 8.1 side by side, which is critical for gradual, safe upgrades.

Create a Gemfile.next that points to Rails 8.1:


# Gemfile.next 

gem "rails", "~> 8.1.0" 

Then use a script (like bin/rails-next) or environment variable (BUNDLE_GEMFILE=Gemfile.next) to toggle between versions. This setup allows you to:

  • Run tests against both versions.

  • Verify fixes without breaking your main branch.

  • Catch compatibility issues early.

Dual booting is especially valuable if your team is large or your release cycle is slow. It turns a big-bang upgrade into a controlled, iterative process.

Step 3: Perform the Actual Rails 8.1 Upgrade

With deprecations resolved and dual booting in place, it’s time to upgrade.

Update your main Gemfile:


gem "rails", "~> 8.1.0" 

Run bundle update rails and resolve any gem conflicts. Some gems may not yet support Rails 8.1, so check their compatibility or consider alternatives.

Run the official Rails update task:


bin/rails app:update 

Review the diffs carefully, especially for config/boot.rb, config/application.rb, and environment files.

Note: schema.rb now sorts columns alphabetically by default. This reduces noisy diffs across environments. If column order matters for your workflow, consider using structure.sql instead.

Step 4: Fix the Broken Build

After the upgrade, your test suite will likely have failures. Common causes include:

  • Removed methods or changed return types.

  • Stricter parameter parsing.

  • Time zone or serialization behavior shifts.

Run your full test suite under Rails 8.1 and fix failures one by one. Pay special attention to integration tests. They often reveal routing or middleware issues missed in unit tests.

If a dependency is incompatible, check for updates or fork it temporarily. Don’t rush to disable tests; understand why they’re failing first.

Step 5: Deploy to Production, Carefully

Once your test suite passes and your app runs smoothly in staging, deploy to production.

But don’t assume you’re done. Monitor error trackers, logs, and performance metrics closely for the first 24–48 hours. Some issues like time zone edge cases or background job failures, only surface under real load.

If you skipped thorough testing, this phase can become chaotic. That’s why the earlier steps matter: they shift risk left, so production stays stable.

Taking the time here is worth it. A stable production release is the real success metric of any Rails 8.1 upgrade.

Conclusion

A successful Rails 8.1 upgrade is less about speed and more about discipline. By addressing deprecations early, dual booting your application, following a proper Rails upgrade checklist, and testing thoroughly, you reduce risk while setting your codebase up for long-term health.

Rails upgrades are an opportunity to clean up technical debt, simplify configurations, and align your application with modern Rails practices. With a structured approach, your Rails 8 upgrade to 8.1 can be predictable, low-stress, and rewarding for your entire team.

If you treat the upgrade as a process rather than a one-time task, Rails 8.1 becomes a solid foundation for future growth.

If you are looking for upgrade help or any Ruby on Rails consulting services, reach out to our team at RailsFactory.

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