Rails “Fat Model” Syndrome: How to Keep Models Skinny
If you’ve ever opened a Rails model and thought, “This file has its own weather system,” you’ve met Rails Fat Model Syndrome.
Rails popularized “Fat Model, Skinny Controller.” But the phrase was never meant to justify turning a model into a small monolith. The goal is domain cohesion, not one-file-to-rule-them-all.
Domain logic: invariants and behavior of the entity (e.g., Order#cancelable?, validations, state transitions)
Orchestration logic: multi-step workflows across boundaries (charge payment, reserve inventory, email, external APIs)
- Service Objects (The “Doer”)
- Concerns (The “Organizer”)
- Query Objects (The “Finder”)
- Value Objects (The “Attribute with a brain”)
- Form Objects (The “Validator for a specific flow”)
So where does the code go?
https://www.digi-archive.com/articles/rails-fat-model-syndrome-skinny-models
app/services/ # business actions (orchestration)
app/queries/ # filtering/search composition
app/forms/ # flow-specific validation + multi-model writes
app/value_objects/ # pure Ruby domain primitives
app/models/concerns/# cross-cutting model behavior