0%
Reading Settings
Font Size
18px
Line Height
1.5
Letter Spacing
0.01em
Font Family
Table of contents
Reducing ActiveRecord Queries to Speed Up Your Requests
Software Engineer
Software Engineer
Ruby on Rails
Ruby on Rails
In Rails, ActiveRecord is one of the things that makes the framework so enjoyable to use. It reads almost like natural language and lets you write database logic in a clean, Ruby-style way.
But every line of Active Record still turns into real SQL behind the scenes. Every SQL query comes with a fixed cost:
- Network latency between your app and the database (even on localhost)
- Query parsing and planning time inside PostgreSQL
- Serialization of results back to Ruby
- Context switching inside your Rails process
By reducing the number of SQL queries, you minimize these fixed costs: fewer round-trips, less time spent parsing and deserializing, and fewer blocking waits inside your Ruby threads, which directly improves your app’s performance.
1. Aggregate Metrics
A common pattern is calculating both sum and count separately:
// language: ruby # Before pipeline_sum = PipelineRun.sum(:time_to_results_finalized) pipeline_count = PipelineRun.count
Each call triggers a separate query. You can combine both metrics in a single SQL scan:
// language: ruby
# After
pipeline_sum, pipeline_count = PipelineRun.pick(
Arel.sql("SUM(time_to_results_finalized)"),
Arel.sql("COUNT(*)")
)✅ Only 1 query
✅ Postgres calculates both in the same scan
2. Counting Conditional Subsets
If you’re counting filtered subsets, don’t run one query per condition.
// language: ruby # Before active_count = User.where(active: true).count inactive_count = User.where(active: false).count
Use Postgres FILTER to compute both in a single pass:
// language: ruby
# After
active_count, inactive_count = User.pick(Arel.sql("
COUNT(*) FILTER (WHERE active = TRUE),
COUNT(*) FILTER (WHERE active = FALSE)
"))
✅ Only 1 query
✅ Postgres calculates both in the same scan
We can use it with more complex conditions:
// language: ruby
User.pick(Arel.sql("
COUNT(*) FILTER (WHERE last_login_at > NOW() - INTERVAL '30 days') AS recent_users,
COUNT(*) FILTER (WHERE confirmed = FALSE) AS unconfirmed_users
"))3. Using .group for Grouped Metrics
Grouping is another easy win. We often loop over values and count them separately:
// language: ruby
# Before
statuses = {}
["draft", "published"].each do |s|
statuses[s] = Post.where(status: s).count
end
Rails can do it all in one query:
// language: ruby
# After
statuses = Post.group(:status).count
# => { "draft" => 12, "published" => 42 }
✅ Only 1 query
✅ Returns a hash directly
✅ Scales linearly even with many groups
4. Loading Metadata & Associated Totals Together
When showing project stats, we often query separately:
// language: ruby # Before project = Project.find(1) tasks_count = project.tasks.count members_count = project.members.count
Three queries total. You can aggregate directly with joins:
// language: ruby
# After
project = Project
.left_joins(:tasks, :members)
.where(id: 1)
.select("projects.*,
COUNT(DISTINCT tasks.id) AS tasks_count,
COUNT(DISTINCT members.id) AS members_count")
.group("projects.id")
.first
✅ Only 1 query
✅ You can access
Conclusion
Rails makes it easy to express queries cleanly, but small inefficiencies add up fast. When you notice multiple .sum , .count , or .where calls in a row, ask yourself:
"Can this be done in one SQL pass?"
"Can this be done in one SQL pass?"
Related blogs
Speed Up Independent Queries Using Rails load_async
When you're building a dashboard, it's common to fetch multiple, independent datasets. The page loading might be slow because it has to fetch all data to render a page. A common solution is using AJAX to load pieces of the dashboard, which is great, ...
Software Engineer
Software Engineer
Ruby on Rails
Ruby on Rails
Hello Golang: My First Steps to the Language
I’ve worked with Ruby in several projects, which is defined as "a programmer’s best friend" for its clean and English-like syntax. While my back-end experience is rooted in the Ruby on Rails framework, I prefer TypeScript for building CLI tools and s...
Software Engineer
Software Engineer