The Business Logic
Framework for Ruby
Build maintainable systems, not just scripts.
See it in Action
From simple tasks to complex workflows, see how CMDx brings clarity to your business logic.
Define a Task
Declare typed attributes with validation, coercion, and defaults. Write your business logic in a single work method with built-in flow control for success, failure, and skip states.
class ApproveLoan < CMDx::Task
on_success :notify_applicant!
required :application_id, type: :integer
optional :override_checks, default: false
def work
if application.nil?
fail!("Application not found", code: 404)
elsif application.approved?
skip!("Already approved")
else
application.approve!
context.approved_at = Time.current
end
end
private
def application
@application ||= LoanApplication.find_by(id: application_id)
end
def notify_applicant!
ApprovalMailer.approved(application).deliver_later
end
end
Execute & React
Every execution returns a standardized Result object. No more rescuing exceptions for control flow. Check the outcome and access returned values, error messages, and metadata.
# Execute with typed, validated arguments
result = ApproveLoan.execute(application_id: 42)
# React to the outcome
if result.success?
puts "Approved at #{result.context.approved_at}"
elsif result.skipped?
puts "Skipped: #{result.reason}"
elsif result.failed?
puts "Failed: #{result.reason}"
puts "Code: #{result.metadata[:code]}"
end
# Bang variant raises on failure
result = ApproveLoan.execute!(application_id: 42)
# => raises CMDx::ExecutionError on failure
Compose Workflows
Chain tasks into declarative pipelines with shared context, conditional execution, and configurable halt behavior. Run tasks in parallel for maximum throughput.
class OnboardCustomer < CMDx::Task
include CMDx::Workflow
# Sequential pipeline
task CreateAccount
task SetupBilling
task AssignPlan
# Parallel notifications
tasks SendWelcomeEmail,
SendWelcomeSms,
CreateDashboard,
strategy: :parallel
# Conditional execution
task ScheduleOnboardingCall,
if: :premium_plan?
private
def premium_plan?
context.plan.tier == :premium
end
end
# Run the entire workflow
result = OnboardCustomer.execute(email: "jane@co.com")
Fault Tolerance
Handle transient failures automatically with configurable retries, selective exception matching, and exponential backoff. No manual intervention needed.
class ProcessPayment < CMDx::Task
settings retries: 5,
retry_on: [Stripe::RateLimitError,
Net::ReadTimeout],
retry_jitter: :exponential_backoff
required :payment_id, type: :integer
def work
payment = Payment.find(payment_id)
context.charge = Stripe::Charge.create(
amount: payment.amount_cents,
currency: "usd",
source: payment.token
)
end
private
def exponential_backoff(current_retry)
2 ** current_retry # 2s, 4s, 8s, 16s, 32s
end
end
result = ProcessPayment.execute(payment_id: 99)
result.retried? # => true
result.retries # => 2
Observe Everything
Every execution automatically generates structured logs with chain IDs, runtime metrics, and contextual metadata. Trace complex workflows and debug issues with ease.
# Structured logs are generated automatically
# with correlation IDs for full traceability
I, [2026-02-06T14:22:01.000 #4891] INFO -- CMDx:
index=0 chain_id="018c..e5"
type="Task" class="CreateAccount"
state="complete" status="success"
metadata={runtime: 12}
I, [2026-02-06T14:22:01.050 #4891] INFO -- CMDx:
index=1 chain_id="018c..e5"
type="Task" class="SetupBilling"
state="complete" status="success"
metadata={runtime: 45}
W, [2026-02-06T14:22:01.200 #4891] WARN -- CMDx:
index=2 chain_id="018c..e5"
type="Task" class="SendWelcomeEmail"
state="complete" status="skipped"
metadata={runtime: 2, reason: "Email not configured"}
I, [2026-02-06T14:22:01.250 #4891] INFO -- CMDx:
index=0 chain_id="018c..e5"
type="Workflow" class="OnboardCustomer"
state="complete" status="success"
metadata={runtime: 250}
Why CMDx?
Designed for developers who value clarity, consistency, and reliability.
Zero Dependencies
Lightweight and pure Ruby. Drop it into Rails, Sinatra, Hanami, or any plain Ruby script without bloating your Gemfile.
Type Safety
Declare inputs with strict typing, coercion, and validation. Catch bad data at the boundary, before it corrupts your logic.
Observability
Built-in tracing, structured logging, and error tracking. Know exactly what happened, when, and why.
Composability
Chain small, focused commands into complex workflows. Reuse logic across your application with confidence.
Predictable Results
No more rescuing exceptions for control flow. Every command returns a standardized Result object.
Production Ready
Includes I18n, retries, deprecation handling, and middleware support out of the box.
The CERO Pattern
A simple mental model for reliable logic.
Build reusable, single-responsibility tasks with typed attributes and validation.
Invoke tasks with a consistent API that handles errors and logging automatically.
Handle standardized result objects with clear success, failure, or skipped states.
Trace execution with structured logs, correlation IDs, and runtime metrics.
How We Compare
CMDx delivers the full stack without the bloat.
| Feature | CMDx | Actor | Interactor | ActiveInteraction | LightService |
|---|---|---|---|---|---|
| Zero Dependencies | ✅ | ✅ | ✅ | ❌ | ✅ |
| Typed Attributes | ✅ | ✅ | ❌ | ✅ | ❌ |
| Type Coercion | ✅ | ❌ | ❌ | ✅ | ❌ |
| Built-in Logging | ✅ | ❌ | ❌ | ❌ | ❌ |
| Middleware System | ✅ | ❌ | ❌ | ❌ | ✅ |
| Fault Tolerance | ✅ | ❌ | ❌ | ❌ | ❌ |
Built For Real World Logic
From simple scripts to complex enterprise workflows.
🏦 Financial Operations
Handle payments, loans, and ledgers with audit trails and transactional integrity.
🔄 Data Pipelines
Structure ETL processes with clear steps, error handling, and resumption capabilities.
🛒 E-commerce
Orchestrate order fulfillment, inventory checks, and shipping logistics reliably.