Framework
rage-rb/rage avatar
rage-rb/rage

Rage Ruby: API framework with a fiber-based unified runtime

Fiber-based Ruby web framework combining Rails ergonomics with a unified runtime

1,445 stars43 forksRubyMIT

At a glance

What is it?
Rage is an API-first Ruby web framework that runs controllers, background jobs, WebSockets, and SSE streams through a fiber-based runtime. It suits developers who want Rails-style application structure without maintaining a separate queue and worker stack.
Who is it for?
Rage fits teams building API services with Ruby that value familiar controller conventions and a compact runtime. It is a weaker choice for applications that require separate workers, external queue providers, or independently scaled process types.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Rage's API-first scope and operational model

Rage addresses the infrastructure burden that appears when a Ruby backend grows beyond request and response handling. The README describes a service that needs background execution, real-time communication, telemetry, and clear domain boundaries, then identifies a common Ruby response: Redis, Sidekiq, separate worker processes, custom logging tools, and multiple deployment units.

Rage takes a different approach. It is designed around a single runtime in which an API, persistent background jobs, WebSocket broadcasts, Server-Sent Events, and domain events execute inside the application process. This is most relevant to developers who can accept that coupling. The simplicity comes from moving those responsibilities into one deployment unit rather than making every capability independently deployable.

The framework still follows familiar Ruby application conventions. The README says it retains controller conventions, routing DSL, Active Record integration, and support for incremental adoption in an existing Rails application. Its target is not arbitrary Ruby web code, but API services that benefit from Rails-style organization while adopting fibers for I/O concurrency. A standalone service created with `rage new` is the main path, while the Rails integration path lets a team introduce Rage selectively to new endpoints or selected routes.

How Rage schedules request fibers and resumes I/O

Rage runs each request in a separate fiber. According to the README, when application code performs an I/O operation such as an HTTP request, database query, or file read, that fiber pauses. The runtime can then process other requests. Once the operation completes, the fiber resumes from the point where it stopped.

This model keeps application code synchronous. The framework does not require `async` or `await` syntax for the request path described in the README. That is the central engineering trade-off: developers write ordinary Ruby control flow, while Rage manages cooperative concurrency beneath it. The approach is presented as avoiding a thread-per-request model and avoiding explicit async syntax, although the README does not describe compatibility with every Ruby I/O library.

The runtime also extends beyond request handling. Background tasks, broadcasts, streams, and domain events share the same process. WebSockets include built-in IPC for multi-process deployments, but the documented example for jobs and broadcasts is explicitly in-process and uses no Redis or separate worker service. Rage therefore offers two related but distinct approaches: request concurrency comes from fibers, while several backend capabilities are consolidated into one runtime. Teams should not interpret that consolidation as automatically providing the independent failure and scaling boundaries of separate services.

Installing Rage and starting the first application

The README uses `gem install rage-rb` to install the framework. It then creates an application named `my_app`, changes into that directory, and installs its bundle dependencies. The repository badge states that Ruby 3.3 or later is required. The following commands reproduce the documented setup sequence.

The install command adds the `rage` executable from the `rage-rb` gem to the local Ruby environment. The README does not provide operating system installation prerequisites beyond the Ruby requirement.

bash
$ gem install rage-rb
$ rage new my_app

After creation, dependency installation uses Bundler from inside the generated application. The reader should end up in the newly generated `my_app` directory.

bash
$ cd my_app
$ bundle install

Rage also provides an optional command for installing agent skills. The README marks this step as optional, so it is not required to start the server.

bash
$ rage skills install

The documented server command is `rage s`. Once it starts, the README directs the reader to `http://localhost:3000`.

bash
$ rage s

That is enough for an initial setup, but it does not demonstrate an endpoint. The README's controller example provides the first concrete use: create an order, enqueue a confirmation task, broadcast the new order, and return JSON. It also shows the comment tags used to describe the request, response, and status code for generated OpenAPI documentation.

ruby
class OrdersController < RageController::API
  # @request { amount: Float, product_id: Integer }
  # @response 201 Order
  def create
    order = Order.create!(order_params)
    SendOrderConfirmation.enqueue(order.id)
    Rage::Cable.broadcast("orders", { status: "created", order_id: order.id })
    render json: order, status: :created
  end
end

The example assumes application models, routing, and an order-parameter method have already been established. The README does not provide a complete first-endpoint tutorial, so it does not document where to register this controller or how to authenticate the request.

Running persistent jobs and real-time channels together

Rage's background-job design is persistent and in-process. A task includes `Rage::Deferred::Task`, receives work through `enqueue`, and performs its work in the application's runtime. The README says the queue is persisted to disk and needs neither Redis nor separate worker processes. That removes an external service from the documented deployment shape.

ruby
class SendOrderConfirmation
  include Rage::Deferred::Task

  def perform(order_id)
    order = Order.find(order_id)
    OrderMailer.confirmation(order).deliver
  end
end

The job example loads an order and sends its confirmation email. The controller that schedules it also broadcasts a compact order event through `Rage::Cable`. These operations share one process, so the deployment remains compact. The trade-off is that the application runtime is also responsible for request handling and the delayed work. The README does not claim that disk persistence provides Redis-like deployment guarantees, and it does not document retry policies, queue isolation, process-crash recovery details, or throughput limits. Those points require direct verification before moving a critical workload.

Real-time communication has two documented forms. WebSockets are described as Action Cable-compatible and include built-in IPC for multi-process deployments. SSE is available natively without an external dependency, with live feeds, progress updates, and LLM response streaming named as intended uses. The order example uses a WebSocket broadcast, while SSE remains a separate transport for one-way server-to-client streams. Rage also provides object-oriented domain events rather than string-based notifications, which can make handlers discoverable in Ruby code.

Generating OpenAPI and adopting Rage beside Rails

Rage treats API documentation as part of the application definition. Its README shows `@request` and `@response` comments beside a controller action, followed by a generated status and model annotation. The stated result is an OpenAPI specification derived from controllers through simple comment tags. This keeps documentation close to endpoint behavior, although the README does not describe validation behavior for incomplete annotations, generated file placement, or customization options.

There are two supported adoption paths. A standalone application starts with `rage new` and provides a project structure and CLI tools intended for APIs built from scratch. An existing Rails application can add Rage for selected endpoints or higher-traffic routes while leaving the rest of the application unchanged. That makes Rage different from a mandatory full replacement for Rails migrations.

The actual difference is architectural placement. Rails remains the larger host application in the integration path, while Rage supplies its runtime and conventions to selected routes. The README does not explain how shared models, authentication, transactional behavior, or application configuration are coordinated across the two frameworks. A team should verify those boundaries with its own application rather than assuming controller compatibility means the entire Rails deployment can be migrated incrementally without changes.

Choosing Rage instead of separate workers and a queue

The closest documented alternative is a conventional Rails service that keeps the web process, queue backend, and worker deployment separate. Rails can use familiar controllers, routing, and Active Record integration, while an external system such as Sidekiq handles background work. The README explicitly names Redis, Sidekiq, and separate worker processes as infrastructure that developers commonly add.

The approaches differ mainly in process topology. Rails-style separation gives request serving and background execution independent process lifecycles and separate scaling decisions. Rage folds jobs into the application process and pauses fibers during I/O. This can reduce the number of services and moving parts for an API whose workload fits that arrangement. It also couples those responsibilities to one runtime.

Rage is therefore the wrong choice when separate worker scaling, queue-provider portability, or independent worker deployment is a firm requirement. A conventional stack may also be clearer when a team already has mature operational procedures around Redis and Sidekiq. Rage becomes more relevant when minimizing infrastructure outweighs those benefits and the application can use disk persistence, WebSockets, SSE, and in-process deferred tasks as documented. The README does not provide a feature-by-feature comparison or migration guide for replacing an existing Sidekiq queue, so adoption should not be framed as a drop-in infrastructure change.

Maintenance, upgrades, dependencies, and MIT terms

The repository is not archived, and its last push was on 2026-10-16. Recent releases include v1.28.0 on 2026-09-15, v1.27.0 on 2026-08-06, and v1.26.0 on 2026-07-07. The repository layout includes `CHANGELOG.md`, `CONTRIBUTING.md`, `ARCHITECTURE.md`, `Gemfile`, `rage.gemspec`, `gemfiles/`, and `spec/`, which gives maintainers defined places for release notes, contribution rules, dependency declarations, architecture documentation, and tests.

The project's stated upgrade policy favors stable public APIs, long deprecation cycles, and minimal external dependencies. The README says most updates should be possible with `bundle update`, but it does not publish a version-by-version migration procedure. Review `CHANGELOG.md` for the relevant release before upgrading, especially if the service relies on generated OpenAPI, deferred tasks, cable broadcasts, or SSE behavior.

Rage is distributed under the MIT License. The repository identifies a permissive open source license, but this review does not interpret its legal effect. Developers should read `LICENSE.txt` and assess their own compliance, notice, dependency, and distribution requirements. The gem's minimal-dependency position may simplify dependency management, while `Gemfile` and `rage.gemspec` remain the relevant files for confirming the versions a particular application resolves.

Editorial conclusion

Rage fits teams building API services with Ruby that value familiar controller conventions and a compact runtime. It is a weaker choice for applications that require separate workers, external queue providers, or independently scaled process types. Before adoption, verify whether fiber compatibility, in-process job durability, and the intended deployment model meet the application requirements. For a new service, start with `rage new my_app` and inspect the generated background-job and WebSocket paths.

Frequently asked questions

Is Rage a Ruby replacement for Rails?

Not exactly. Rage keeps Rails-style controllers, routing, and Active Record integration, but it can also be added to selected routes in an existing Rails application for incremental migration.

Does Rage need Redis for background jobs?

The README says Rage deferred tasks use a persistent in-process queue and do not require Redis or separate worker processes.

How does Rage handle concurrent Ruby requests?

Rage assigns each request to a separate fiber and pauses that fiber during I/O so the runtime can process other requests. Application code remains synchronous according to the README.

Official sources

  1. License: MIT
  2. Project website
  3. rage-rb/rage on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rage-rb-rage.svg)](https://hysenlabs.com/projects/rage-rb-rage)

Was this useful?