Rails 8.1 new API: `Rails.event.notify(...)`

Rails 8.1 new API: `Rails.event.notify(...)`

Rails 8.1 is set to bring a new API, Rails.event.notify(...), that will help make it simple to publish structured events that are immediately consumable by monitoring and Application Performance Monitoring (APM) platforms like Datadog, AppSignal, New Relic, or Honeycomb.

In this post, we’ll look at how it works, why it matters, and how to prepare your app for data-hungry observability tools.

The Problem: Rails AS::Notifications and Scattered Instrumentation

If you’ve ever tried to add observability to a Rails app, you’ve probably touched ActiveSupport::Notifications API. It offers flexibility, but requires boilerplate code and can be inconsistent across projects.

Many applications rely on third-party services like Datadog, AppSignal, and others, each with their own conventions and wrappers. This often leads to challenges for maintainers, such as dealing with fragmented APIs, risk of vendor lock-in, balancing useful insights against excessive noise, and navigating compliance issues.

Example: Integrating with Datadog

Datadog can consume Rails events by subscribing to them and forwarding them as traces or metrics.

# config/initializers/datadog.rb
Datadog.configure do |c|
  c.instrument :rails
end

ActiveSupport::Notifications.subscribe("checkout.completed") do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)

  Datadog.statsd.increment(
    "rails.checkout.completed",
    tags: ["order_id:#{event.payload[:order_id]}", "env:#{Rails.env}"]
  )
end

In Rails 8.1 a simple call to Rails.event.notify("checkout.completed", order_id: order.id) will be captured by Datadog as a metric. Check out the Datadog Ruby APM Docs. opens a new window

Example: Integrating with AppSignal

AppSignal already hooks into ActiveSupport::Notifications, so integration is usually seamless:

# config/initializers/appsignal.rb
ActiveSupport::Notifications.subscribe("user.login") do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)

  Appsignal.increment_counter(
    "rails.user.login",
    1,
    user_id: event.payload[:user_id]
  )
end

Whenever you call:

Rails.event.notify("user.login", user_id: current_user.id)

…it will appear in AppSignal dashboards as a custom counter.

📖 Reference: AppSignal Ruby Docs opens a new window

The new API Rails.event.notify(...)

Rails 8.1 introduces a new, unified API for event emission:

The default logger in Rails is great for human consumption, but less ideal for post-processing. The new Event Reporter provides a unified interface for producing structured events in Rails applications:

Rails.event.notify("checkout.completed", order_id: order.id, amount: order.total_cents)

It supports adding tags to events:

Rails.event.tagged("graphql") do
  # Event includes tags: { graphql: true }
  Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
end

As well as context:

# All events will contain context: {request_id: "abc123", shop_id: 456}
Rails.event.set_context(request_id: "abc123", shop_id: 456)

Events are emitted to subscribers. Applications register subscribers to control how events are serialized and emitted. Subscribers must implement an #emit method, which receives the event hash:

class LogSubscriber
  def emit(event)
    payload = event[:payload].map { |key, value| "#{key}=#{value}" }.join(" ")
    source_location = event[:source_location]
    log = "[#{event[:name]}] #{payload} at #{source_location[:filepath]}:#{source_location[:lineno]}"
    Rails.logger.info(log)
  end
end

This API has a few key properties:

  • Structured events organized by namespace (such as checkout.completed or user.login).
  • Tool-agnostic: no need to write custom code for Datadog, AppSignal, or New Relic.
  • Built on Rails’ internal notification system, so it remains lightweight.
  • Provides a standardized approach for consistent instrumentation across the Rails community.

Why This Matters for Observability

With Rails.event.notify(...), Rails applications gain the ability to emit consistent events throughout the system, integrate seamlessly with APM tools without the need for custom glue code, and improve performance insights by correlating application-level events with low-level metrics. This standardization also helps reduce developer overhead by providing a unified instrumentation API.

This new feature also makes it easier to get your app ready for AI tools and data warehouses. By sending out clear, organized events, your Rails app can give useful data to machine learning systems, analytics tools, or big data storage. This helps automate tasks, find helpful patterns, and make smarter decisions as your app grows.

Best Practices for Event Design

  • When designing events, use a clear namespace format such as resource.action (for example, checkout.completed).
  • Keep payloads minimal by including only necessary details like IDs, amounts, and status, and avoid adding sensitive or personally identifiable information.
  • Focus on instrumenting high-value events rather than everything, and wrap notifications in helper methods to ensure consistency across your codebase.
module Instrumentation
  def self.checkout_completed(order)
    Rails.event.notify("checkout.completed", order_id: order.id, amount: order.total_cents)
  end
end

Conclusion

This new API lowers the barrier to structured instrumentation and ensures your app is ready to be consumed by any third-party application you want to use.

Future versions of Rails may tighten this integration even further, encouraging teams to treat events as first-class citizens in their applications.

Rails has always been about developer happiness, and now it’s also about developer visibility.

Ready to upgrade your Rails app and get ready for Rails 8.1? Let’s talk opens a new window .

Get the book