
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
✔️ Valid paths between states
✔️ Optional guards and callbacks
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 ForProsConsAASMMost Rails appsEasy, powerfulCan get complexstate_machineLegacy appsClean DSLUnmaintainedStatesmanAuditable workflowsLogs + structureMore boilerplateWorkflowLightweight 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.
