Active Record allows developers to mark associations as deprecated, providing robust reporting mechanisms to identify and eliminate their usage across all environments.
It supports multiple reporting modes and configurable backtraces, making the process of cleaning up or removing associations much safer and more efficient.
Before
We had no built-in way to deprecate associations. Removing an association like this:
has_many :projects
meant deleting projects
and hoping CI or manual testing would catch all usage. This is risky in production, especially with incomplete test coverage or mocked associations.
After
Rails introduces deprecated: true for the deprecated associations. With this, Active Record warns every time the association is used.
We can easily mark an association as deprecated by adding the :deprecated
option to our has_many
, belongs_to
, or other association declarations before deleting them.
class Client < ApplicationRecord
has_many :projects, deprecated: true
end
With this, Active Record will begin reporting any usage of the projects
association.

Rails supports three reporting modes—:warn
, :raise
, and :notify
— with the option to enable or disable backtraces as needed.
By default, :warn
mode is enabled
and backtraces are disabled.
Configuration & Behavior
We can select one of three modes to control how usage is handled:
-
:warn
(default): Logs a warning via the Active Record logger. We can enable clean backtraces to help trace the source. -
:raise:
Raises anActiveRecord::DeprecatedAssociationError
. Best for test and development environments where we want usage to fail fast. Always includes a clean stack trace. -
:notify:
Emits an Active Support notification:deprecated_association.active_record
. This mode is ideal for integrating with custom monitoring systems like Sentry, New Relic or other observability tools. The payload includes::reflection
— the association object:message
— the kind of usage (e.g., post_ids):location
— where it happened:backtrace
— optional, for full context
By default, backtraces are disabled. But if usage is indirect or triggered from shared code, enabling backtraces helps:
# config/application.rb
config.active_record.deprecated_associations_options = { mode: :warn, backtrace: true }
Backtraces are clean, filtered using the Rails.backtrace_cleaner
, so we get relevant application-level locations without noise.
We can set the behavior for all deprecated associations across our app:
# config/application.rb
config.active_record.deprecated_associations_options = { mode: :notify, backtrace: true }
This ensures consistency across environments and simplifies the rollout of deprecations at scale.
Refer