September 25, 2026

Active Search, Meet Bonsai: Ruby on Rails Search on Managed OpenSearch

Ruby on Rails has a search framework of its own now. At Rails World 2026, Donal McBreen from 37signals, the company behind Basecamp and Rails itself, introduced Active Search. It gives you one chainable, Active Record style interface for full-text search across OpenSearch, Elasticsearch, Solr, Meilisearch, Typesense and friends, as well as the full-text search built into PostgreSQL, MySQL and SQLite.

If you've written search in Rails before, you know the drill: pick a gem, learn its DSL, marry it forever. Active Search changes that. Start on your database today, move to a managed search cluster when your app outgrows it, and your models and controllers stay the same. It's alpha software (0.1.0 on RubyGems as I write this), but it already runs against OpenSearch, which means it runs against Bonsai.

Active Search vs Searchkick and Chewy

Searchkick and Chewy are built for Elasticsearch and OpenSearch, and expose a lot of what those engines can do (we compared the Ruby gems a while back). Active Search is a common interface instead, the way Active Record is for databases, so the same Article.search("rails") works on SQLite in development and OpenSearch in production. The trade-off: no aggregations, nested documents or autocomplete yet. If you need those today, Searchkick is still a great fit.

Step 1: Add Active Search to your Rails app

Active Search doesn't bundle a search client. Bonsai clusters run OpenSearch, so bring opensearch-ruby:

# Gemfile
gem "rails-active_search"
gem "opensearch-ruby"
bundle install
bin/rails active_search:install

Step 2: Connect Active Search to your Bonsai cluster

Grab your cluster URL from the Access section of your cluster dashboard. Heroku users already have it in BONSAI_URL.

# config/search.yml
development:
  adapter: sqlite

production:
  adapter: opensearch
  hosts:
    - <%= ENV["BONSAI_URL"] %>

The client reads the host, port and credentials straight out of the URL (our Active Search docs cover the full setup). Development runs on SQLite, production runs on Bonsai, and your app doesn't know the difference.

Step 3: Define a search index and connect your model

# config/search.rb
ActiveSearch.define_index(:articles) do
  text :title
  text :body
  string :status
end
# app/models/article.rb
class Article < ApplicationRecord
  has_search
end

text fields are searched, the rest are for filtering and sorting. has_search adds callbacks that reindex a record on every save and remove it on destroy, through Active Job.

Step 4: Create the index and load your data

bin/rails active_search:index:create INDEX=articles

The callbacks only fire on new writes, so batch your existing records in from a console:

ActiveSearch.index(:articles).batch(max_size: 500) do |batch|
  Article.find_each { |article| batch.add(article) }
end

Step 5: Search from your Rails controller

# app/controllers/articles_controller.rb
def index
  @page = Article.search(params[:q])
    .filter(status: "published")
    .page(params[:page], per_page: 20)
end

It chains like the Active Record queries you already write, and pagination is built in. Loop over @page.results in your view and each result is the record itself.

See what your Rails search is doing in the Bonsai dashboard

Active Search writes the queries for you. That's the whole point, but it's also why it's worth having somewhere to see them land.

Documents: did the load actually work?

Run bin/rails active_search:status COUNT=1, then compare it with the Usage panel on your cluster's Overview:

Usage panel showing document, data and shard counts

If your database says 5,000 articles and Bonsai says 5K docs, you're done. If not, you know before your users do.

Performance: your traffic, at a glance

Performance heat map

Each column in the Overview heat map is a slice of time, each row a bucket of request duration, and hotter colors mean more requests. A cool, tight band at the bottom? Happy cluster. Heat creeping upward right after a deploy? You just found your slow query, and you know exactly when it started.

Query Logs: what your users are really asking

Query Logs panel on the cluster overview

Query Logs ranks the search terms your users type by volume, with duration and hit count for each. High volume with low hits is a relevancy problem, and zero-hit queries are the first thing to fix. To tell Bonsai exactly what the user typed, add it to the request with native:

Article.search(params[:q]).native { |request|
  request.merge(ext: { bonsai: { user_query: params[:q] } })
}.page(params[:page])

The Console: talk to your cluster directly

Bonsai Console running the Active Search query

Want to see what Active Search is sending? Article.search("hotwire").to_native_query returns the request body. Paste it into the Console as a POST to /articles/_search and tweak it until the results look right. No curl, no credentials on your clipboard.

Why Active Search and Bonsai work well together

Active Search makes the engine swappable. Bonsai makes the engine visible. Together you get Rails-native search code and a cluster you can actually see into, without running a single node yourself.

Spin up a free Sandbox cluster, add the gem, and watch your first queries light up the heat map. The Active Search README covers everything this post skipped, and we'd love to hear how you're using it at support@bonsai.io.

Ready to power your search with AI?

Launch a fully managed Elasticsearch or OpenSearch cluster, with built-in vector search and AI capabilities.

Learn how a managed service works and why it’s valuable to dev teams

You won’t be pressured or used in any manipulative sales tactics

We’ll get a deep understanding of your current tech stack and needs

Get the information you need to decide whether to go with Bonsai

Create an AI Ready Search Cluster

Or, schedule a consultation:

Calming Bonsai waves