Stacks vs Ruby on Rails

Rails proved the case. Stacks argues it again in TypeScript.

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.

What Ruby on Rails is.

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.

Where each one wins.

Same amount of room on both sides, on purpose.

Pick Ruby on Rails for

  • If you align with DHH

    We don’t want you here.

Pick Stacks for

  • Static types across the boundary

    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.

  • One language with the front end

    No context switch between Ruby on the server and TypeScript in the browser, and no duplicated types.

  • Schema from models

    The model is the source of truth and migrations are diffed from it, instead of schema.rb being derived from migration history.

  • Provisioning, DNS, and mail too

    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.

  • Your own mail server

    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.

Side by side.

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

If you did move.

What ports cleanly, what does not, and where to start.

Active Record models become defineModel()

Associations, validations, callbacks, and scopes have direct counterparts as relationships, attribute rules, and traits.

Controllers become actions

A controller action is a Stacks action; strong parameters become model-declared validation.

Jobs move nearly unchanged

Active Job classes and Stacks jobs have the same shape, including retries and queues.

The verdict.

Both answers are real. Most teams already know which paragraph is theirs.

Choose Ruby on Rails when

Your team is Ruby, or you want the most refined convention-driven framework in existence with two decades of answers behind it.

Choose Stacks when

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.