Active Record adds support for deprecating associations

Chirag Shah avatar

Chirag Shah

July 3, 2025

Active Record adds support for deprecating associations

In Rails 8, we can now mark Active Record associations as deprecated. This makes it easy to phase out old associations from our codebase, while still keeping them around to safely remove their usages. Whenever a deprecated association is used, whether by calling the association, executing a query that references it, or triggering a side‑effect like :dependent or :touch, Rails will alert us according to our chosen reporting mode.

Marking an association as deprecated

Simply pass the deprecated: true option when declaring an association.

class User < ApplicationRecord
  has_many :meetings, deprecated: true
end

Now, every time the meeting association is invoked, we’ll get a deprecation warning in our logs.

> user.meetings
The association User#meetings is deprecated, the method meetings was invoked ((calendar):4:in '<main>')

> User.includes(:meetings).where(id: 1)
The association User#meetings is deprecated, referenced in query to preload records ()

> User.joins(:meetings).where(id: 1)
The association User#meetings is deprecated, referenced in query to join its table ()

Working with different association types

We can deprecate any association type.

class Order < ApplicationRecord
  # has_many
  has_many :line_items, deprecated: true

  # belongs_to
  belongs_to :customer, deprecated: true

  # has_one
  has_one :profile, deprecated: true

  # has_many through
  has_many :archived_comments, through: :comments, deprecated: true
end

Reporting modes and backtrace support

This feature supports three deprecation modes:

  • :warn (default) Logs a warning to our Active Record logger.
  • :raise Raises an exception when the deprecated association is used.
  • :notify Emits an Active Support notification event with the key deprecated_association.active_record. This can be used to send notifications to external services like Honeybadger etc. We can check the details about its payload here.

Backtraces are disabled by default. If :backtrace is true, :warn mode will include a clean backtrace in the message, and :notify mode will have a backtrace key in the payload. Exceptions raised via :raise mode will always have a clean stack trace.

We can change the global default mode in an initializer.

# config/initializers/deprecated_associations.rb
ActiveRecord.deprecated_associations_options = {
  mode: :warn,      # :warn | :raise | :notify
  backtrace: true   # whether to include a cleaned backtrace
}

It can also be set at an environment level.

# config/environments/development.rb
Rails.application.configure do
  config.active_record.deprecated_associations_options = { mode: :raise, backtrace: true }
end

# config/environments/production.rb
Rails.application.configure do
  config.active_record.deprecated_associations_options = { mode: :warn, backtrace: true }
end

Why deprecate rather than remove?

In large applications, it’s often hard to guarantee complete test coverage. Some association usages may only surface in production.

Deprecating an association first, lets us:

  • Identify every code path (tests, console, background jobs) that relies on it.
  • Gradually refactor those references before removal.
  • Ensure confidence that deleting the association won’t break anything unexpectedly.

This new feature in Rails provides a clean and intuitive way to phase out our associations with deprecation warnings, making it easier to maintain and refactor large codebases.

This feature was merged recently, and will be released in the next Rails minor/patch version.

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.