Pick Ruby on Rails for
-
If you align with DHH
We don’t want you here.
Every framework on this page owes Rails something: convention over configuration, generators, migrations, an ORM with opinions, and the idea that one person should be able to build a whole product. Stacks agrees with all of it and differs on the two things Rails cannot change, which are the language and the runtime.
In its own terms, not ours.
Rails is twenty years old and better than ever. Hotwire made server-rendered HTML competitive with single-page applications again, Solid Queue and Solid Cable removed Redis from the default stack, and Kamal made deployment to your own servers straightforward. Its productivity for a small team is still the reference point everyone measures against.
Same amount of room on both sides, on purpose.
We don’t want you here.
Ruby is dynamically typed and Sorbet or RBS is optional. In Stacks the compiler checks the model, the action, the view, and the client together.
No context switch between Ruby on the server and TypeScript in the browser, and no duplicated types.
The model is the source of truth and migrations are diffed from it, instead of schema.rb being derived from migration history.
Kamal deploys to servers you already have. buddy deploy can also create them on Hetzner or AWS, adopt any Linux box over SSH, and manage DNS and mail records, and Stacks can run its own SMTP and IMAP server on the same box.
Stacks ships an SMTP and IMAP server, so hello@ and support@ on your domain are real mailboxes on your own box, readable in Mail.app or any client. buddy mail:provision creates them and their MX, SPF, DKIM, and DMARC records. None of the frameworks compared here ships one.
The dimensions teams actually decide on.
| Dimension | Stacks | Ruby on Rails |
|---|---|---|
| Language | TypeScript, statically checked | Ruby, dynamically typed |
| ORM | defineModel(), migrations generated | Active Record, migrations hand-written |
| Views | STX: SSR, SSG, islands, signals | ERB with Hotwire |
| Background work | Queues on database, Redis, or sync drivers | Active Job with Solid Queue |
| Realtime | Channels and model broadcasts | Action Cable and Turbo Streams |
| Auth | Passkeys, 2FA, social login, RBAC, built in | Generator plus Devise or Pundit |
| Deploy | buddy deploy to Hetzner, AWS, or any SSH box | Kamal to any servers |
| Admin | Generated dashboard | ActiveAdmin or Avo |
| Mail server | Built in: SMTP, IMAP, real mailboxes | Action Mailbox routes inbound mail; inboxes are a provider |
What ports cleanly, what does not, and where to start.
Associations, validations, callbacks, and scopes have direct counterparts as relationships, attribute rules, and traits.
A controller action is a Stacks action; strong parameters become model-declared validation.
Active Job classes and Stacks jobs have the same shape, including retries and queues.
Both answers are real. Most teams already know which paragraph is theirs.
Your team is Ruby, or you want the most refined convention-driven framework in existence with two decades of answers behind it.
You want those conventions with static types across the whole stack, and one language shared with the browser.
The frameworks that usually come up in the same conversation.