
Understanding State Machines in Ruby: Concepts, Examples & the Best Gems
November 21, 2025
State machines are one of the cleanest and most reliable ways to model workflows in software. If your system needs to move through predictable steps — orders, payments, approvals, devices, tickets — a state machine ensures everything transitions cleanly and safely.
In Ruby and Rails, they’re extremely powerful. Here’s a quick guide to the concept, a simple example, and a comparison of the top gems.
What Is a State Machine?
A Finite State Machine (FSM) models four things:
States (e.g., pending, approved, rejected)
Events that trigger transitions
It protects your system from invalid behavior — like shipping an order before being paid.
Simple Example (No Gem)
class Order
STATES = %i[pending paid shipped delivered].freeze
attr_reader :state
def initialize
@state = :pending
end
def pay ; transition_to(:paid) if state == :pending; end
def ship ; transition_to(:shipped) if state == :paid; end
def deliver ; transition_to(:delivered) if state == :shipped; end
private
def transition_to(new_state)
puts "Transition: #{state} → #{new_state}"
@state = new_state
end
end
Great for understanding the idea — but real apps benefit from a gem.
The Most Popular Ruby State Machine Gems
1⃣ AASM (Recommended for Most Rails Apps)
One of the most widely adopted solutions in the Ruby ecosystem.
Pros
- Clean, readable DSL
- Rails-friendly
- Guards, callbacks, multiple machines
- Good community support
Cons – Can get complex in large workflows – DSL flexibility can lead to messy code if not organized
Example:
aasm do
state :pending, initial: true
state :paid
state :shipped
event :pay { transitions from: :pending, to: :paid }
event :ship { transitions from: :paid, to: :shipped }
end
2⃣ state_machine (Classic but Unmaintained)
The original DSL many people loved.
Pros
- Beautiful DSL
- Mature and stable historically
Cons – Not actively maintained – Many forks, fragmented ecosystem
Use for legacy apps — not ideal for new ones.
3⃣ Statesman (Audit-Friendly Workflows)
A different philosophy: transitions are stored in a database table.
Pros
- Excellent for compliance and history tracking
- Clean architecture
- Great for long, complex workflows
Cons – More boilerplate – No model callbacks – Might be too heavy for simple apps
4⃣ Workflow (Lightweight Ruby FSM)
Perfect if you want something tiny and fast.
Pros
- Small and simple
- Great for non-Rails Ruby apps
Cons – Less popular in Rails – Fewer advanced features
So… Which One Should You Use?
GemBest ForProsCons AASM Most Rails appsEasy, powerfulCan get complex state_machine Legacy appsClean DSLUnmaintained Statesman Auditable workflowsLogs + structureMore boilerplate Workflow Lightweight RubySimple + fastFewer features
Final Thoughts
State machines bring clarity and safety to your domain logic. If you’re building a modern Rails app today, AASM is usually the cleanest choice. For audit-heavy systems, Statesman stands out.


Top comments (0)