Record domain events and dispatch to inbox handlers for side effects, audit trails, and activity feeds. Use when building activity logs, syncing external services, or decoupling event creation from processing. Triggers on event recording, audit trails, activity feeds, or inbox patterns.
View on GitHubmajesticlabs-dev/majestic-marketplace
majestic-rails
plugins/majestic-rails/skills/event-sourcing-coder/SKILL.md
January 24, 2026
Select agents to install to:
npx add-skill https://github.com/majesticlabs-dev/majestic-marketplace/blob/main/plugins/majestic-rails/skills/event-sourcing-coder/SKILL.md -a claude-code --skill event-sourcing-coderInstallation paths:
.claude/skills/event-sourcing-coder/# Event Sourcing for Rails Monoliths
Record significant domain events and dispatch them to specialized handlers - a pragmatic approach to event sourcing without the complexity of full CQRS/ES infrastructure.
## When to Use This Skill
- Building activity feeds or audit trails
- Syncing data to external services (CRMs, analytics, webhooks)
- Automating workflows triggered by domain events
- Decoupling "what happened" from "what to do about it"
- Tracking user actions for analytics or debugging
## When NOT to Use Events
| Scenario | Better Alternative |
|----------|-------------------|
| Simple callbacks on single model | ActiveRecord callbacks |
| Synchronous side effects only | Service objects or ActiveInteraction |
| Need full event replay/rebuilding | Dedicated event sourcing gem (Rails Event Store) |
| Single handler per event | Direct method calls |
## Core Concept
**Decouple recording from processing:**
```
User action → Record Event → Broadcast to Inboxes → Side Effects
↓
Queryable
(audit trail)
```
## Setup
### Migration
```ruby
class CreateIssueEvents < ActiveRecord::Migration[8.0]
def change
create_table :issue_events do |t|
t.references :issue, null: false, foreign_key: true
t.references :actor, null: false, foreign_key: { to_table: :users }
t.string :action, null: false
t.jsonb :metadata, default: {}
t.timestamps
end
add_index :issue_events, :action
add_index :issue_events, :created_at
end
end
```
### Event Model
```ruby
# app/models/issue/event.rb
module Issue::Event
extend ActiveSupport::Concern
ACTIONS = %w[
created
assigned
status_changed
commented
closed
reopened
].freeze
included do
belongs_to :issue
belongs_to :actor, class_name: "User"
validates :action, presence: true, inclusion: { in: ACTIONS }
after_commit :broadcast_to_inboxes, on: :create
end
private
def broadcast_to_inboxes