Ruby on Rails is an exceptional framework for developing prototypes and minimum viable products (MVPs) for the web. However, its opinionated nature and specific architectural tradeoffs mean it is not the universal answer for every engineering challenge.
- The Ruby programming language is compact, yet expressive and powerful.
- Rails is robust and has a proven track record—it powers successful companies such as Airbnb, Github, and Shopify—providing interactive and dynamic page updates, caching mechanisms, form handling, rich text editing, background jobs, integration with all popular database servers, and more.
- Performance of Ruby, long derided as subpar compared to Python and Go, is substantially improved in Ruby 3 and Ruby 4: Just-in-time compilation (JIT), threads, and non-blocking I/O more than tripled runtime performance. Speed remains a priority of the Ruby core development team. (JIT results in Ruby 3.3 were 13% faster than version 3.2.) Ruby 4.0 further reduces global lock contention, minimizes shared internal state, and improves CPU cache behavior.
- Ruby and Rails have strong community support. Blogs, forums, and Slack channels are active, helpful, and prolific. Ruby developers can draw from an extensive ecosystem of open source gems (Ruby parlance for code libraries) to ease development and integration.
- Ruby on Rails is secure. Built-in security features include authentication and sessions and protection against common vulnerabilities such as SQL injection, cross-site request forgery (CSRF), and cross-site scripting (XSS).
Rails is also far from derelict. Each major release of Rails includes innovations intended to reduce or avoid rote, boilerplate code and boost developer productivity.
Rails Feature Comparison
If you haven’t looked closely at Ruby on Rails in a few years, it’s easy to assume it’s standing still while other frameworks race ahead. In practice, Rails has been evolving steadily. Recent releases push harder on performance, security, and reducing boilerplate so small teams can move faster.
If your last Rails app was on Rails 4 or 5, the framework will feel familiar but noticeably less clunky. Recent releases changed practical things: how you handle rich text and email, how much JavaScript you ship, and whether you need Redis at all. The table below shows what actually shifted in Rails 6, 7, and 8.
The following table captures some of the evolutions, improvements, and new features added to the most recent releases of Rails (2019-2024).
| Feature | Rails 6 (2019) | Rails 7 (2021) | Rails 8 (2024) |
| Rich Text | Introduces Action Text and integrates Trix editor for WYSIWYG editing. Handles file uploads and storage automatically. | ||
| Email Handling | Introduces Action Mailbox to route incoming email to controller-like mailboxes for processing (e.g., reply-to-post). | ||
| Frontend Assets | Webpacker is the default pipeline. Relies heavily on Node and Yarn. | Import Maps becomes the new default. Node is not required. ES modules are served directly to the browser. | Propshaft becomes the new default. It is a modern, simpler asset pipeline tailored for HTTP/2. |
| UI Interactivity | Turbolinks + UJS (Unobtrusive JavaScript) provides common conveniences. | Hotwire (Turbo + Stimulus) replaces Turbolinks. HTML is sent over-the-wire for SPA-like speed without JSON APIs. | Hotwire adds morphing for smoother page updates. |
| Background Jobs | Active Job unifies the interface to background job systems but requires external Redis/Sidekiq for production. | Active Job adds support for async queries. | Solid Queue replaces Redis with a high-performance, DB-backed job backend. |
| Caching | Redis/Memcached is usually required. | Solid Cache replaces Redis with DB-backed caching. Uses fast SSDs/SQL instead of RAM/Redis. | |
| Authentication | Adds has_secure_password. | Generates scaffolded controllers/models for auth. No external gem dependencies. | |
| Database Support | Adds multi-DB support (Primary/Replica). | Adds encrypted attributes. | Optimizes configurations (WAL mode, etc.) to make SQLite a viable production DB. |
All told, Ruby on Rails hastens the rapid development of web applications. Indeed, Rails is often called a “one-person framework.” With it, a sole developer or a small development team can focus on features, trusting rudiments to the framework, to realize remarkable gains. Developer productivity is the substantive reason that successful startups and established endeavors adopt and continue to use Rails.
If your application is intended for the web and is backed by a relational database, or if you want to launch and iterate rapidly, reach for Rails. Experienced Ruby developers and contractors are fairly easy to hire, too.
When Ruby on Rails is Not the Right Choice for MVP Development
However advantageous, Rails is not necessarily the best solution for all problems. Your problem may not be in scope; your problem may require magnitude; or it may be your organization or team is simply not a good fit. Let’s examine each consideration.
It’s a Matter of Scope
As mentioned in the introduction, Rails is an expansive framework with tools for database access, rendering web pages, background processing, email, and more. While you can pare or ignore most of those features if need be (Rails is increasingly modular), the core intent of the framework remains. If your application is tiny, simple, or commonplace, Rails is likely overkill.
For example, if your application is a static site, a blog, or a marketing site (a brochure site), you are likely better served with other, more tailored solutions or commercial software. Even a small retail store is out of scope of Rails because building with Rails would reinvent the wheel. You could use Rails to manage inventory, effectuate payments, manage shipping, and so on. However, there is little advantage to a bespoke solution when a plethora of e-commerce platforms are extant and cheap.
A shim is likely another misapplication of Rails. A shim is an intermediary service dedicated to preprocessing and perhaps reprocessing requests. For example, a shim might enforce rate limits and reject a torrent of requests or may capture, analyze, and reroute a request to another internal service. A classic shim is a single API endpoint that consumes one or more other endpoints and assembles a unified, perhaps minimized response. Mobile apps commonly consume data from such a specialized endpoint.
A shim typically requires high throughput but performs relatively simple tasks sans the need for database connections or complex logic. Rails’ features incur too much overhead for practical use as a shim. AWS Lambda, Go, or Rust are superior for infrastructure “glue” because overhead per operation is negligible.
It’s a Matter of Magnitude
While one problem may be out of Ruby on Rails’s scope because it falls to meet a threshold for features, another problem may be unsuitable because its demands preclude Rails.
Computationally-intensive applications are one category outside the purview of Rails. For compute-intensive workloads, Ruby lacks the speed of a compiled language and the retinue of scientific libraries. For massively concurrent applications, Ruby’s architecture cannot sustain hundreds of thousands of open connections without massive allocations of hardware and banks of RAM. The limits on concurrency also eliminate or narrowly curtail Rails usage in high-frequency trading, multiplayer real-time gaming, and wide-scale data streaming.
Ruby has garnered a number of artificial intelligence and machine learning libraries of late, but Python remains the leading option for the data sciences.
Highly concurrent applications are another exception. Elixir and Go are optimized for massive concurrency.
It’s a Matter of Fit
Even if Rails is a purposeful and technological fit, the framework may not be a practical or cultural fit for your organization.
Two important considerations, especially in highly-regulated industries such as healthcare and banking, are risk minimization and auditability. An application that manages patient records, for instance, must be shown to be correct before it runs in production. Here, statically-typed languages such as Java and C# are favored because many classes of errors—typos, type mismatches (adding an integer to a string), and missing variable declarations—can be detected at compile-time. Static Application Security Testing (SAST) can be further applied to validate code quality.
Ruby is a dynamically-typed language and cannot pass the same muster. Indeed, many of Ruby’s most appealing and differentiating features are something of anathema to compliance.
| Ruby Feature | Behavior | Compliance Risk |
| Dynamic typing | Types are checked at run-time | Type mismatches are not detected until the errant code executes.. |
| Metaprogramming | Code can be created and altered during run-time. | A security scanner (even humans) cannot predict all possible code paths because the code can alter itself at any time. |
| Monkey-patching | Core and library code can be affected without changing the original source code. | It is difficult to accurately track dependencies and bugs are arduous to find. |
In Ruby, any variable can contain any value of any type at any time. Variables need not be declared before use. Moreover, running code can alter itself, a technique called metaprogramming, and libraries can (if intended to) affect each other since a Ruby class may be “reopened” at will. Ruby may not be an option depending on your industry and regulatory hurdles.
Separate from the Ruby language, Rails may prove incongruous if your organization prefers or requires a highly opinionated architecture. Rails “favors convention over configuration”—projects have identical file hierarchies and naming schemes, applications adhere to the Model-View-Controller (MVC) pattern, and database interactions occur via ActiveRecord—but does not impose any architecture constraints. Each development team can choose its own patterns and typically assembles its own approach to infrastructure. Thus, each Rails application is alike but also divergent.
For comparison, consider Spring Boot (for Java, Kotlin, and Groovy): Spring Boot defines an architecture and reinforces the design with tools, documentation, explicitly bounded contexts, and well-understood, ingrained patterns. Every Spring Boot application is layered —controller, service, repository, and domain—and even disparate projects converge to common development practices and definitions of classes, interfaces, and modules.
Spring Boot is a framework and a discipline, making many decisions on the behalf of a development team. Its constraints discourage architectural drift, those configuration and coding variances that complicate and inflate maintenance and future development. If you run a large organization with multiple project teams, such predictability may trump freedom. Teams can cross-pollinate and onboarding is easier since projects are enforceably uniform.
NestJS (Typescript) and Laravel (PHP) are two other opinionated architecture frameworks.
Adopt Ruby on Rails or Other Frameworks?
Rails is not an aging framework. Its capabilities grow with each release and benefit from underlying performance enhancements made to the Ruby programming language itself. You may favor Rails for new construction because your development team is Ruby savvy or you already have a suite of Rails applications in production. The technology stack is proven in production environments.
But there are circumstances where Rails is not apropos. Whether you should choose Rails for your application depends on your specific requirements, circumstances, even timing. As developers are wont to say, “Uh, it depends.”
You may disfavor Rails if your local area lacks a readily available pool of Rails developers or if your requirements are not well aligned with the capabilities of the Ruby language and runtimes. Your organization may benefit from a stricter structure offered by a more opinionated framework such as Spring Boot. You may be required by regulation to prove your application correct.
Here are some guidelines to help you decide whether or not to adopt a Rails stack.
| If this is your priority… | Rails is usually a good fit when… | Another framework is usually better when… |
| Time-to-market & MVP development | You want faster development, less repetitive code, and an MVP quickly. | You can afford a slower start to optimize raw performance early. |
| Workload shape | Your app mostly manipulates user-generated, relational data (CRUD). | Your app is compute-intensive, streaming, or heavily data-crunching. |
| Architecture & infrastructure | You prefer a robust, secure, stable, unified monolith. | You want to lean hard on serverless or fine-grained microservices. |
| Latency and concurrency at extreme scale | “Good enough” performance with simpler ops is acceptable. | You require minimal latency and maximal concurrency. |
Generally, if you want to maximize developer productivity and launch quickly, choose Rails. If you require maximum raw performance or want to enforce constraints, choose another technology.

